如何正确清理Python对象? [英] How do I correctly clean up a Python object?

查看:141
本文介绍了如何正确清理Python对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

class Package:
    def __init__(self):
        self.files = []

    # ...

    def __del__(self):
        for file in self.files:
            os.unlink(file)

上面的

__ del __(self)失败,并出现AttributeError异常。我了解 Python不能保证存在全局变量(成员数据)在这种情况下?)何时调用 __ del __()。如果是这种情况,并且这是导致异常的原因,那么如何确保对象正确销毁?

__del__(self) above fails with an AttributeError exception. I understand Python doesn't guarantee the existence of "global variables" (member data in this context?) when __del__() is invoked. If that is the case and this is the reason for the exception, how do I make sure the object destructs properly?

推荐答案

I建议使用Python的 with 语句来管理需要清除的资源。使用显式 close()语句的问题是,您必须担心人们会忘记完全调用它,或者忘记将其放在中最后块以防止发生异常时资源泄漏。

I'd recommend using Python's with statement for managing resources that need to be cleaned up. The problem with using an explicit close() statement is that you have to worry about people forgetting to call it at all or forgetting to place it in a finally block to prevent a resource leak when an exception occurs.

要在和语句,使用以下方法创建一个类:

To use the with statement, create a class with the following methods:

  def __enter__(self)
  def __exit__(self, exc_type, exc_value, traceback)

在上面的示例中,您将使用

In your example above, you'd use

class Package:
    def __init__(self):
        self.files = []

    def __enter__(self):
        return self

    # ...

    def __exit__(self, exc_type, exc_value, traceback):
        for file in self.files:
            os.unlink(file)

然后,当有人想要使用您的类,他们将执行以下操作:

Then, when someone wanted to use your class, they'd do the following:

with Package() as package_obj:
    # use package_obj

变量package_obj将是Package类型的实例( __ enter __ 方法返回的值)。无论是否发生异常,它的 __ exit __ 方法都会自动被调用。

The variable package_obj will be an instance of type Package (it's the value returned by the __enter__ method). Its __exit__ method will automatically be called, regardless of whether or not an exception occurs.

您甚至可以接受此方法更进一步。在上面的示例中,仍然可以使用其构造函数实例化Package,而无需使用 with 子句。您不希望这种情况发生。您可以通过创建PackageResource类来解决此问题,该类定义 __ enter __ __ exit __ 方法。然后,将在 __ enter __ 方法中严格定义Package类并返回。这样,调用者将永远无法在不使用 with 语句的情况下实例化Package类:

You could even take this approach a step further. In the example above, someone could still instantiate Package using its constructor without using the with clause. You don't want that to happen. You can fix this by creating a PackageResource class that defines the __enter__ and __exit__ methods. Then, the Package class would be defined strictly inside the __enter__ method and returned. That way, the caller never could instantiate the Package class without using a with statement:

class PackageResource:
    def __enter__(self):
        class Package:
            ...
        self.package_obj = Package()
        return self.package_obj

    def __exit__(self, exc_type, exc_value, traceback):
        self.package_obj.cleanup()

您将按以下方式使用它:

You'd use this as follows:

with PackageResource() as package_obj:
    # use package_obj

这篇关于如何正确清理Python对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆