我阅读不同的方式来清理对象在Python中,我已经对这些问题跌跌撞撞(1,2)基本上说,清理使用__del__()是不可靠的,下面的代码应避免:
def __init__(self):
rc.open()
def __del__(self):
rc.close()
Run Code Online (Sandbox Code Playgroud)
问题是,我正在使用这个代码,我无法重现上述问题中引用的任何问题.据我所知,我不能用with声明来替代,因为我为闭源软件提供了一个Python模块(testIDEA,任何人?)这个软件将创建特定类的实例并处理它们,这些实例必须准备好在两者之间提供服务.__del__()我看到的唯一替代方法是手动调用open()并close()根据需要,我认为这将非常容易出错.
我明白,当我关闭解释器时,不能保证我的对象会被正确销毁(并且它不会打扰我,哎呀,即使是Python作者也认为它没问题).除此之外,我是否通过__del__()清理来玩火?
PS:我最初想在meta上发布一个关于无法复制的错误问题的咆哮,但意识到我不会得到我需要的技术细节.
您观察到垃圾收集语言中终结器的典型问题。Java 有,C# 有,它们都提供了一个基于作用域的清理方法,比如 Pythonwith关键字来处理它。
主要问题是垃圾收集器负责清理和销毁对象。在 C++ 中,对象在超出范围时会被销毁,因此您可以使用 RAII 并具有明确定义的语义。在 Python 中,对象超出范围并且只要 GC 喜欢就一直存在。根据您的 Python 实现,这可能会有所不同。带有基于引用计数的 GC 的 CPython 是相当良性的(所以你很少看到问题),而 PyPy、IronPython 和 Jython 可能会让一个对象存活很长时间。
例如:
def bad_code(filename):
return open(filename, 'r').read()
for i in xrange(10000):
bad_code('some_file.txt')
Run Code Online (Sandbox Code Playgroud)
bad_code泄漏文件句柄。在 CPython 中,这无关紧要。引用计数降至零并立即删除。在 PyPy 或 IronPython 中,您可能会遇到 IOErrors 或类似问题,因为您用尽了所有可用的文件描述符(ulimit在 Unix 上最多可达509 个句柄,在 Windows 上最多可达509 个句柄)。
使用上下文管理器进行基于范围的清理,with如果您需要保证清理,则更可取。您确切地知道您的对象何时最终确定。但有时您无法轻松执行这种范围清理。那是您可能会使用__del__,atexit或类似的构造来尽最大努力进行清理的时候。它不可靠,但总比没有好。
您可以通过显式清理或强制执行显式范围来增加用户的负担,或者您可以冒险__del__并偶尔看到一些奇怪的东西(尤其是解释器关闭)。
| 归档时间: |
|
| 查看次数: |
906 次 |
| 最近记录: |