我认为Python Processes在终止时会调用它们的atexit函数。请注意,我使用的是Python 2.7。这是一个简单的例子:
from __future__ import print_function
import atexit
from multiprocessing import Process
def test():
atexit.register(lambda: print("atexit function ran"))
process = Process(target=test)
process.start()
process.join()
我希望这会打印“atexit function ran”,但事实并非如此。
请注意这个问题: Python process won't call atexit 类似,但它涉及以信号终止的进程,答案涉及拦截该信号。这个问题中的进程正在优雅地退出,所以(据我所知,无论如何)这个问题&答案不适用(除非这些进程因某种方式的信号而退出?)。
答案 0 :(得分:3)
我通过研究如何在CPython中实现它来做了一些研究。假设您在Unix上运行。如果您在Windows上运行,则以下可能无效,因为multiprocessing
中的流程实现不同。
事实证明,os._exit()
始终在流程结束时被调用。这与atexit文档中的以下注释一起,可以解释为什么你的lambda没有运行。
注意:当通过此模块注册的功能时不会被调用 当一个Python时,程序被Python处理的信号杀死 检测到致命的内部错误,或者调用os._exit()时。
这里是CPython 2.7的Popen
类的摘录,用于分叉过程。请注意,分叉进程的最后一个语句是对os._exit()
的调用。
# Lib/multiprocessing/forking.py
class Popen(object):
def __init__(self, process_obj):
sys.stdout.flush()
sys.stderr.flush()
self.returncode = None
self.pid = os.fork()
if self.pid == 0:
if 'random' in sys.modules:
import random
random.seed()
code = process_obj._bootstrap()
sys.stdout.flush()
sys.stderr.flush()
os._exit(code)
在Python 3.4中,如果您正在启动分叉过程,os._exit()
仍然存在,这是默认值。但似乎您可以更改它,有关详细信息,请参阅Contexts and start methods。我还没有尝试过,但也许使用 spawn 的启动方法会有效吗?但不适用于Python 2.7。