class Package:
def __init__(self):
self.files = []
# ...
def __del__(self):
for file in self.files:
os.unlink(file)
上面的__del__(self)失败,出现AttributeError异常。我理解当调用__del__()时,Python不保证存在“全局变量”(在此上下文中是成员数据?)如果是这种情况,这是异常的原因,我如何确保对象销毁正确?
标准的方法是使用atexit.register:
# package.py
import atexit
import os
class Package:
def __init__(self):
self.files = []
atexit.register(self.cleanup)
def cleanup(self):
print("Running cleanup...")
for file in self.files:
print("Unlinking file: {}".format(file))
# os.unlink(file)
但是您应该记住,这将保存所有已创建的Package实例,直到Python终止。
演示使用上述代码保存为package.py:
$ python
>>> from package import *
>>> p = Package()
>>> q = Package()
>>> q.files = ['a', 'b', 'c']
>>> quit()
Running cleanup...
Unlinking file: a
Unlinking file: b
Unlinking file: c
Running cleanup...
下面是一个最小的工作框架:
class SkeletonFixture:
def __init__(self):
pass
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
pass
def method(self):
pass
with SkeletonFixture() as fixture:
fixture.method()
重要:返回自我
如果你像我一样,忽略了(克林特·米勒正确答案中的)“回归自我”部分,你将会看到下面这段废话:
Traceback (most recent call last):
File "tests/simplestpossible.py", line 17, in <module>
fixture.method()
AttributeError: 'NoneType' object has no attribute 'method'
希望它能帮助到下一个人。
只要用try/except语句包装你的析构函数,如果你的全局变量已经被处理了,它就不会抛出异常。
Edit
试试这个:
from weakref import proxy
class MyList(list): pass
class Package:
def __init__(self):
self.__del__.im_func.files = MyList([1,2,3,4])
self.files = proxy(self.__del__.im_func.files)
def __del__(self):
print self.__del__.im_func.files
它会将文件列表填充到del函数中,该函数保证在调用时存在。weakref代理是为了防止Python或您自己删除self。Files变量(如果它被删除,那么它不会影响原始文件列表)。如果即使有更多对变量的引用,也没有删除该变量,那么可以删除代理封装。