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'
我花了半天時間。 但願它能幫助下一我的。