如何正确清理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'

我花了半天时间。 但愿它能帮助下一我的。

相关文章
相关标签/搜索