我正在使用 python 2.5 编写一个守护程序。在主进程中,向atexit
模块注册了退出处理程序,似乎每个子进程结束时都会调用处理程序,这不是我所期望的。
我注意到python doc中没有提到这种行为atexit
,有人知道这个问题吗?如果这是它的行为方式,我如何在子进程中取消注册退出处理程序?3.0 版本中有一个 atexit.unregister,但我使用的是 2.5。
我正在使用 python 2.5 编写一个守护程序。在主进程中,向atexit
模块注册了退出处理程序,似乎每个子进程结束时都会调用处理程序,这不是我所期望的。
我注意到python doc中没有提到这种行为atexit
,有人知道这个问题吗?如果这是它的行为方式,我如何在子进程中取消注册退出处理程序?3.0 版本中有一个 atexit.unregister,但我使用的是 2.5。
当您fork
创建子进程时,该子进程是父进程的精确副本——当然包括注册的退出函数以及所有其他代码和数据结构。我相信这就是您正在观察的问题——当然,它并没有在每个模块中都提到,因为它必然适用于每个模块。
在 Python 2.5 中没有 API 可以做到这一点,但您可以:
import atexit
atexit._exithandlers = []
在您的子进程中 - 如果您知道您只安装了一个退出处理程序,并且没有安装其他处理程序。但是,请注意 stdlib 的某些部分(例如logging
)注册atexit
处理程序。为避免踩踏它们,您可以尝试:
my_handler_entries = [e for e in atexit._exithandlers if e[0] == my_handler_func]
for e in my_handler_entries:
atexit._exithandlers.remove(e)
my_handler_func
您注册的处理程序在哪里atexit
,这应该删除您的条目而不删除其他条目。
atexit.register()
基本上将您的函数注册在 中atexit._exithandlers
,这是一个模块私有函数列表,由sys.exitfunc()
. 您可以设置exitfunc()
为自定义退出处理程序函数,然后检查子状态或简单地取消注册它。将 3.0 复制atexit.py
到本地源代码树并改用它怎么样?
编辑:我从我的 2.6 版本中复制了 atexit.py 并将其扩展为
def unregister(func, *targs, **kargs):
_exithandlers.remove((func, targs, kargs))
如果您使用它而不是原始版本,它应该可以工作。不过,我还没有使用子流程对其进行测试。