如何正确清理Python对象? [英] How do I correctly clean up a Python object?
问题描述
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屋!