4

我正在使用 python 2.5 编写一个守护程序。在主进程中,向atexit模块注册了退出处理程序,似乎每个子进程结束时都会调用处理程序,这不是我所期望的。

我注意到python doc中没有提到这种行为atexit,有人知道这个问题吗?如果这是它的行为方式,我如何在子进程中取消注册退出处理程序?3.0 版本中有一个 atexit.unregister,但我使用的是 2.5。

4

3 回答 3

4

当您fork创建子进程时,该子进程是父进程的精确副本——当然包括注册的退出函数以及所有其他代码和数据结构。我相信这就是您正在观察的问题——当然,它并没有在每个模块中都提到,因为它必然适用于每个模块。

于 2009-06-27T17:14:18.263 回答
3

在 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,这应该删除您的条目而不删除其他条目。

于 2009-06-30T09:28:56.763 回答
1

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))

如果您使用它而不是原始版本,它应该可以工作。不过,我还没有使用子流程对其进行测试。

于 2009-06-27T12:13:21.533 回答