【问题标题】:Using __del__ properly when referencing external resources引用外部资源时正确使用 __del__
【发布时间】:2021-08-16 22:30:04
【问题描述】:

我正在处理一个不以 Python 方式处理其资源的外部库。该库本身是一个 C++ 库,周围有一个 Python 包装器。每当库函数返回一个 C++ 对象时,我实际得到的是它的字符串句柄。对象本身一直存在于内存中,直到我以该句柄作为参数显式调用 delete() 函数。我试图在句柄周围引入我自己的包装器,以确保当包装器超出范围时将其删除。像这样的:

#import some_module as sm
class MyWrapper(str):
  def __new__(*args, **kwargs):
    # do something
  def __del__(self):
    sm.delete(self)

这在大多数情况下都有效,但在脚本完成时,我经常得到一个异常,说 sm 没有属性 delete。看起来模块对象在我的句柄包装之前被破坏了。有没有办法确保在卸载模块之前调用我的__del__

【问题讨论】:

  • 你的包装类是如何使用的?使用__exit__ 而不是__del__ 可能更有意义,然后使用with 来处理生命周期。
  • __del__ 不保证何时调用它。在 python 中,明确地进行资源管理通常会更好,因为对象的生命周期不是由它们的词法范围决定的。所以基本上,上下文管理
  • @Carcigenicate:我想过,但我通常有很多重叠使用的句柄
  • 您当前的实现不会有同样的问题吗?一旦包装句柄的包装器之一被破坏,您就会破坏底层对象。

标签: python resource-management


【解决方案1】:

解释器关闭可能会以任意顺序清除模块。通过将它们绑定为默认值,将所有需要的清理函数本地存储在__del__中:

class MyWrapper(str):
  def __new__(*args, **kwargs):
    # do something
  def __del__(self, _delete=sm.delete):
    _delete(self)

由于默认值受定义约束并一直保留到函数本身被删除,所以只要函数/方法存在,_delete 将保持原始 sm.delete 可用。


请注意,__del__ 可以在任意时间调用,包括从不调用。将它用作最后的手段通常是个好主意:提供其他方式显式释放对象(例如支持with.close()/.delete() 方法)并编写@987654329 @ 以这样一种方式,如果对象已经被释放,它什么都不做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-18
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    相关资源
    最近更新 更多