class Package: def __init__(self): self.files = [] # ... def __del__(self): for file in self.files: os.unlink(file)
__del__(self)
失败,并出现AttributeError异常。 我了解在调用__del__()
时, Python不保证 “全局变量”(在这种状况下是否存在成员数据__del__()
存在。 若是是这种状况,而且这是致使异常的缘由,那么如何确保对象正确销毁? html
我认为问题可能出在__init__
若是代码多于所示? python
即便未正确执行__init__
或引起异常,也会调用__del__
。 框架
资源 函数
做为克林特答案的附录,您可使用contextlib.contextmanager
简化PackageResource
: ui
@contextlib.contextmanager def packageResource(): class Package: ... package = Package() yield package package.cleanup()
另外,尽管可能不如Pythonic,可是您能够覆盖Package.__new__
: spa
class Package(object): def __new__(cls, *args, **kwargs): @contextlib.contextmanager def packageResource(): # adapt arguments if superclass takes some! package = super(Package, cls).__new__(cls) package.__init__(*args, **kwargs) yield package package.cleanup() def __init__(self, *args, **kwargs): ...
并with Package(...) as package
。 3d
为了contextlib.closing
,请将您的清理函数命名为close
并使用contextlib.closing
,在这种状况下,您能够经过with contextlib.closing(Package(...))
使用未修改的Package
类,也能够将其__new__
重写为更简单的方法 code
class Package(object): def __new__(cls, *args, **kwargs): package = super(Package, cls).__new__(cls) package.__init__(*args, **kwargs) return contextlib.closing(package)
并且此构造函数是继承的,所以您能够简单地继承,例如 orm
class SubPackage(Package): def close(self): pass
标准方法是使用atexit.register
: htm
# 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...
更好的选择是使用weakref.finalize 。 请参见终结器对象和将终结器与__del __()方法进行比较中的示例。
这是一个最小的工做框架:
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()
重要提示: 返回自我
若是您像我同样,却忽略了return self
部分( 克林特·米勒的正确答案的一部分 ),那么您将盯着这个废话:
Traceback (most recent call last): File "tests/simplestpossible.py", line 17, in <module> fixture.method() AttributeError: 'NoneType' object has no attribute 'method'
我花了半天时间。 但愿它能帮助下一我的。