如何正確清理Python對象?

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


#1樓

我認爲問題可能出在__init__若是代碼多於所示? python

即便未正確執行__init__或引起異常,也會調用__del__框架

資源 函數


#2樓

做爲克林特答案的附錄,您可使用contextlib.contextmanager簡化PackageResourceui

@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 package3d

爲了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

#3樓

標準方法是使用atexit.registerhtm

# 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...

#4樓

更好的選擇是使用weakref.finalize 。 請參見終結器對象將終結器與__del __()方法進行比較中的示例。


#5樓

這是一個最小的工做框架:

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'

我花了半天時間。 但願它能幫助下一我的。

相關文章
相關標籤/搜索