在atexit中引用其他模块

4 投票
1 回答
2055 浏览
提问于 2025-04-15 21:12

我有一个函数,负责在程序结束时杀掉一个子进程:

class MySingleton:
    def __init__(self):
        import atexit
        atexit.register(self.stop)

    def stop(self):
        os.kill(self.sel_server_pid, signal.SIGTERM)

但是当这个函数被调用时,我收到了一个错误信息:

Traceback (most recent call last):
File "/usr/lib/python2.5/atexit.py", line 24, in _run_exitfuncs
   func(*targs, **kargs)
File "/home/commando/Development/Diploma/streaminatr/stream/selenium_tests.py", line 66, in stop
   os.kill(self.sel_server_pid, signal.SIGTERM)
AttributeError: 'NoneType' object has no attribute 'kill'

看起来在调用 atexit 之前,ossignal 这两个模块被卸载了。重新导入它们可以解决这个问题,但我觉得这种情况有点奇怪——这些模块在我注册处理程序之前就已经导入了,为什么在我自己的退出处理程序运行之前它们又被卸载了呢?

1 个回答

9

在程序结束时,无法保证事物被销毁的顺序,所以最好让通过atexit注册的函数是自给自足的。比如,在你的情况下:

class MySingleton:
    def __init__(self):
        import atexit
        atexit.register(self.stop)
        self._dokill = os.kill
        self._thesig = signal.SIGTERM

    def stop(self):
        self._dokill(self.sel_server_pid, self._thesig)

这样做比重新导入模块要好(重新导入模块可能会导致程序结束时变慢,甚至出现无尽的循环,虽然对于像os这样的“系统提供”的模块,这种风险较小)。

撰写回答