在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
?
答案 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解释了为什么在多处理功能完成时不会发生这种情况。