为什么不调用__del__方法?

时间:2017-10-26 14:53:21

标签: python python-3.x python-multiprocessing circular-reference finalizer

在python3' multiprocess中,无法调用__del__方法。

我已经阅读了有关循环引用的其他问题,但我无法在multiprocess中找到这种情况。

foo中有一个循环引用,__del__会在foo被直接调用时被调用,但在multiprocess __del__永远不会被调用

import multiprocessing
import weakref


class Foo():
    def __init__(self):
        self.b = []

    def __del__(self):
        print ('del')


def foo():
    print ('call foo')
    f = Foo()
    a = [f]
    # a = [weakref.ref(f)]
    f.b.append(a)


# call foo in other process
p = multiprocessing.Process(target=foo)
p.start()
p.join()


# call foo
foo()

输出:
打电话给foo 打电话给你 德尔

为什么__del__未调用p

2 个答案:

答案 0 :(得分:1)

分叉Process对象在使用os._exit()运行任务后终止,http://sqlfiddle.com/#!17/b4bab/1强制终止子进程,而不用正常清理Python在退出时执行。不清理循环垃圾(因为过程终止而没有给循环GC一个机会运行),它只是掉在地板上,让操作系统清理干净。

这是故意的,因为正常退出(调用所有正常的清理过程)会冒失败的事情,比如未刷新的缓冲区在父项和子项中都被刷新(输出加倍),以及分叉进程继承父项的所有状态时所涉及的其他怪异但除非被明确告知,否则不应该使用它。

答案 1 :(得分:1)

问题实际上并不是为什么未在multiprocess中调用,而是为什么在其他示例中调用 。答案是,当你致电foo时,它不会被调用。它在程序结束时调用。由于程序已经完成,Python知道其他任何东西都可以清理,即使它仍然被引用,所以它清理了循环引用。

如果您在脚本末尾添加print语句,或者从REPL调用此语句,则可以看到在您的第二次__del__来电时仍未调用foo或者,只是在剧本的最后。

鉴于Python在脚本结束时清理循环引用,ShadowRanger's answer解释了为什么在多处理功能完成时不会发生这种情况。