我正在阅读有关清理Python对象的不同方法,并且偶然发现了这些问题(1,2),这些问题基本上说使用__del__()
进行清理是不可靠的,应避免使用以下代码:
def __init__(self):
rc.open()
def __del__(self):
rc.close()
问题是,我恰好使用了这段代码,并且无法重现以上问题中引用的任何问题。就我所知,我无法使用
with
语句来替代,因为我为封闭源软件(testIDEA,有人吗?)提供了Python模块。该软件将创建特定类的实例并进行处理,这些实例必须准备好在两者之间提供服务。我看到的__del__()
的唯一替代方法是根据需要手动调用open()
和close()
,我认为这很容易发生错误。我了解,当我关闭解释器时,不能保证我的对象将被正确销毁(并且不会打扰我,哎呀,甚至Python作者都认为还可以)。 除此之外,我是否通过使用
__del__()
进行清理来玩火? 最佳答案
您会观察到垃圾回收语言中的终结器的典型问题。 Java拥有它,C#拥有它,并且它们都提供了基于范围的清理方法,例如Python with
关键字来处理它。
主要问题是,垃圾收集器负责清理和销毁对象。在C++中,对象超出范围时将被销毁,因此您可以使用RAII并具有明确定义的语义。在Python中,只要GC喜欢,对象就会超出范围并继续存在。根据您的Python实现,这可能有所不同。 CPython及其基于引用计数的GC相当不错(因此您很少看到问题),而PyPy,IronPython和Jython可能会使对象存活很长时间。
例如:
def bad_code(filename):
return open(filename, 'r').read()
for i in xrange(10000):
bad_code('some_file.txt')
bad_code
泄漏文件句柄。在CPython中没关系。引用计数降至零,并立即删除。在PyPy或IronPython中,由于耗尽所有可用的文件描述符(Unix上的ulimit
或Windows上的509句柄),您可能会遇到IOError或类似问题。如果您需要保证清理,则最好使用上下文管理器和
with
进行基于范围的清理。您确切地知道何时完成对象。但是有时您无法轻松实现这种范围的清理。那就是当您可能使用__del__
,atexit
或类似结构尽最大努力进行清理时。它不可靠,但总比没有好。您可以通过显式清理或强制使用显式作用域来加重用户负担,也可以使用
__del__
进行赌博,然后时不时地看到一些奇怪的地方(尤其是解释器关闭)。关于python - 在Python中依靠__del __()进行清理是否不可靠?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35488705/