程序结束时__del__

时间:2010-08-24 09:07:08

标签: python

假设在运行时存在一个包含几个对象的程序。

程序结束时是否调用了每个对象的__del__方法?

如果是,我可以做一些这样的事情:

class Client:
  __del__( self ):
    disconnect_from_server()

4 个答案:

答案 0 :(得分:7)

使用__del__有很多potential difficulties。 通常,没有必要,或者最好自己定义它。

相反,如果您想要一个在退出或异常后自行清理的对象,请使用context manager

根据Carl的评论:

class Client:
    def __exit__(self,ext_type,exc_value,traceback):
        self.disconnect_from_server()

with Client() as c:
    ...

原始回答:

import contextlib

class Client:
    ...

@contextlib.contextmanager
def make_client():
    c=Client()
    yield c
    c.disconnect_from_server()

with make_client() as c:
    ...

答案 1 :(得分:5)

我的第二个概念是使用上下文管理器和with语句而不是依赖__del__(出于同样的原因,人们更喜欢尝试/最终使用Java中的终结器方法,加上一个:in Python,__del__方法的存在可以使循环垃圾无法收集。

然而,鉴于目标是“退出或异常后自行清理的对象”,@ ~unutbu的实现正确:

@contextlib.contextmanager
def make_client():
    c=Client()
    yield c
    c.disconnect_from_server()

with make_client() as c:
    ...

如果在...部分引发了异常,disconnect_from_server_会调用而非(因为异常通过make_client传播,在那里未被捕获,并且因此,当它在yield)等待时终止它。

修复很简单:

@contextlib.contextmanager
def make_client():
    c=Client()
    try: yield c
    finally: c.disconnect_from_server()

基本上,with语句让你几乎忘记了旧的try / finally语句... 除了,当你编写上下文管理器时contextlib,然后记住它真的很重要! - )

答案 2 :(得分:2)

考虑使用with-statement来明确清理。 使用循环引用__del__不会被调用:

class Foo:
  def __del__(self):
    self.p = None
    print "deleting foo"

a = Foo()
b = Foo()
a.p = b
b.p = a

什么都不打印。

答案 3 :(得分:1)

是的,Python解释器在关闭时整理,包括调用每个对象的__del__方法(参与周期中的对象除外)。

虽然正如其他人所指出的那样,__del__方法非常脆弱,应谨慎使用。