异常后的对象垃圾回收
我发现,在发生异常后,有一个对象的构造函数没有被调用,这导致了一个锁被保持着。有什么好的方法来改善这种情况吗?在异常处理块中调用del会是解决办法吗?
b=BigHash(DB_DIR, url)
meta = bdecode(b.get())
return meta
b持有一个锁,这个锁在对象被销毁时会释放(这是一个C++对象)。异常是由b.get()引发的。
3 个回答
在名字上使用 del
这个操作,基本上是你不应该做的事情。使用 del
并不能保证你对底层对象会有什么有用的影响。 你绝对不应该依赖 __del__
方法来完成你需要的事情。
del
只是删除了一个对象的引用,这可能会让人感到困惑,因为你可能在不经意间创建了多个引用。因此,del
适合用来清理命名空间,而不是用来控制对象的生命周期,而且它在这方面也不是特别好——控制一个名字的生命周期的正确方法是把它放在一个函数里,让它超出作用域,或者放在一个 with 块中。
你需要给 BigHash
添加一个能够显式释放锁的功能,比如 release
、unlock
或 close
方法。如果你想和上下文管理器(with
)一起使用,可以定义 __exit__
方法,这样它会在一个可预测且有用的时机被调用。
无论发生什么,你都希望能够释放锁,不管是否抛出了异常。在这种情况下,最好在一个 finally:
代码块中释放锁或删除 b:
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
你也可以使用上下文管理器,具体可以参考这个链接:http://docs.python.org/library/stdtypes.html#typecontextmanager。只需在 BigHash.__exit__
函数中添加代码来释放锁,这个函数会在你离开 with
代码块后被调用,下面的代码就是一个例子:
with BigHash(DB_DIR, url) as b:
meta = bdecode(b.get())
return meta
你需要做一些事情来确保 b 是解锁状态
b=BigHash(DB_DIR, url)
try:
meta = bdecode(b.get())
return meta
finally:
#unlock b here
如果 BigHash 能作为一个上下文来使用,那就会更简单,这样你可以写
with b as BigHash(DB_DIR, url):
meta = bdecode(b.get())
return meta
不过,你可能需要在 BigHash 中添加一些代码,让它能作为上下文使用