I have observed that after an exception I have an object for which constructor is not called, which causes a lock to be held. What is the best way to improve the situation? Would calling del in an except block be the solution?
b=BigHash(DB_DIR, url)
meta = bdecode(b.get())
return meta
b holds a lock which is 开发者_如何学Creleased on destruction (it's a C++ object) an exception is thrown by b.get().
No matter what, you want the lock to be released - whether or not an exception is thrown. In that case, it's probably best to release the lock/delete b in a finally:
clause:
b=BigHash(DB_DIR, url)
try:
meta = bdecode(b.get())
finally:
del b # or whatever you need to do to release the lock
return meta
You could also use a context manager - http://docs.python.org/library/stdtypes.html#typecontextmanager. Simply add code to free the lock in the BigHash.__exit__
function, which will be called after leaving the with
block in the following code:
with BigHash(DB_DIR, url) as b:
meta = bdecode(b.get())
return meta
You need to do something like this to make sure b in unlocked
b=BigHash(DB_DIR, url)
try:
meta = bdecode(b.get())
return meta
finally:
#unlock b here
A cleaner way would be if BigHash can work as a context, so you can write
with b as BigHash(DB_DIR, url):
meta = bdecode(b.get())
return meta
You might have to add some code to BigHash to make it work as a context though
Calling del
on a name is something you prettymuch never should do. Calling del
does not guarantee anything useful about what will happen to the underlying object. You should never depend on a __del__
method for something you need to happen.
del
only gets rid of one reference to an object, which can be confusing when you may have made more without thinking. Therefore, del
is useful for cleaning up a namespace, not for controlling the lifetime of objects, and it's not even great for that—the proper way to control a name's lifetime is to put it in a function and have it go out of scope or put it in a with block.
You need to equip BigHash
with the ability to release the lock explicitly, with an release
or unlock
or close
method. If you want to use this with a context manager (with
), you can define __exit__
, which will get called at a predictable, useful time.
精彩评论