异常后的对象垃圾回收

1 投票
3 回答
1281 浏览
提问于 2025-04-15 19:28

我发现,在发生异常后,有一个对象的构造函数没有被调用,这导致了一个锁被保持着。有什么好的方法来改善这种情况吗?在异常处理块中调用del会是解决办法吗?

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

b持有一个锁,这个锁在对象被销毁时会释放(这是一个C++对象)。异常是由b.get()引发的。

3 个回答

0

在名字上使用 del 这个操作,基本上是你不应该做的事情。使用 del 并不能保证你对底层对象会有什么有用的影响。 你绝对不应该依赖 __del__ 方法来完成你需要的事情。

del 只是删除了一个对象的引用,这可能会让人感到困惑,因为你可能在不经意间创建了多个引用。因此,del 适合用来清理命名空间,而不是用来控制对象的生命周期,而且它在这方面也不是特别好——控制一个名字的生命周期的正确方法是把它放在一个函数里,让它超出作用域,或者放在一个 with 块中。

你需要给 BigHash 添加一个能够显式释放锁的功能,比如 releaseunlockclose 方法。如果你想和上下文管理器(with)一起使用,可以定义 __exit__ 方法,这样它会在一个可预测且有用的时机被调用。

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

你需要做一些事情来确保 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 中添加一些代码,让它能作为上下文使用

撰写回答