异常后的对象垃圾收集

时间:2010-02-19 11:45:15

标签: python exception-handling destructor

我观察到在异常之后我有一个没有调用构造函数的对象,这会导致锁定。改善这种情况的最佳方法是什么?在一个except块中调用del是解决方案吗?

b=BigHash(DB_DIR, url)
meta = bdecode(b.get())
return meta

b持有一个在销毁时释放的锁(它是一个C ++对象) b.get()抛出异常。

3 个答案:

答案 0 :(得分:3)

无论如何,您都希望释放锁定 - 无论是否抛出异常。在这种情况下,最好在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

答案 1 :(得分:1)

您需要执行以下操作以确保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添加一些代码,以使其作为上下文工作

答案 2 :(得分:0)

在姓名上调用del是你从未做过的事情。 调用del并不保证对底层对象会发生什么有用。您永远不应该依赖__del__方法来处理您需要发生的事情。

del只能删除一个对象的引用,这可能会让你在没有思考的情况下做出更多的事情时感到困惑。因此,del对于清理命名空间非常有用,而不是用于控制对象的生命周期,而它甚至不是很好 - 控制名称生命周期的正确方法就是放置它在一个函数中,让它超出范围或将其放在一个块中。

您需要让BigHash能够使用releaseunlockclose方法明确释放锁 。如果要将其与上下文管理器(with)一起使用,则可以定义__exit__,这将在可预测的有用时间进行调用。