python - Python 脚本中有多个 SIGTERM 处理程序 - 谁应该调用 sys.exit()?
问题描述
假设我有以下脚本:
import signal
import sys
class Klass:
def __init__(self, name):
self.name = name
def disconnect_gracefully(*args):
print(self.name)
sys.exit()
signal.signal(signal.SIGINT, disconnect_gracefully)
a = Klass("A")
b = Klass("B")
while True:
pass
请注意,这两个类在 SIGINT 之后都有一个优雅的退出。当我运行它并 crtl-c 时,只打印“B”。
一般来说,在这样的情况下,应该打电话给谁或什么sys.exit()
- 两种情况都应该,都不应该?
解决方案
信号的 Python 文档仅说明了多次为同一信号设置处理程序时会发生什么:
特定信号的处理程序一旦设置,将保持安装状态,直到显式重置
和
[调用时
signal.signal
] 将返回上一个信号处理程序
这似乎意味着,就像 POSIX 信号一样,一个进程一次只能有一个处理给定信号的处理程序。
我们可以在您的程序中添加一些语句来显示signal.signal
返回的内容(在 CPython 中):
import signal
import sys
class K:
def __init__(self, name):
self.name=name
def disconnect(*args):
print(self.name)
sys.exit()
self.disconnectfuncid=id(disconnect)
self.oldsig=signal.signal(signal.SIGINT, disconnect)
>>> a=K("a")
>>> hex(a.disconnectfuncid)
'0x7fc5c1057f28'
>>> a.oldsig
<built-in function default_int_handler>
>>> signal.getsignal(signal.SIGINT)
<function K.__init__.<locals>.disconnect at 0x7fc5c1057f28>
>>> b=K("b")
>>> hex(b.disconnectfuncid)
'0x7fc5c0ed0950'
>>> b.oldsig
<function K.__init__.<locals>.disconnect at 0x7fc5c1057f28>
>>> signal.getsignal(signal.SIGINT)
<function K.__init__.<locals>.disconnect at 0x7fc5c0ed0950>
>>> while True:
... pass
...^C b
所以处理程序从 开始<built-in function default_int_handler>
,然后设置为实例中的函数,然后设置为实例中的disconnect
函数,后者是传递信号时调用的函数。a
disconnect
b
如果您想在收到 SIGINT 时退出,并在退出前运行多个函数,一种方法是调用以下命令(这将禁止打印回溯和KeyboardInterrupt
消息):
signal.signal(signal.SIGINT, lambda *args: sys.exit())
然后使用atexit.register注册每个函数。
推荐阅读
- node.js - 哈希摘要更新功能如何工作?
- c# - 在 Update() 之外创建的变量
- sql - 选择只有一个关联值不在预定义列表中的所有元素
- php - PHPDocumenter 类没有总结
- mysql - SQL 获取名字和姓氏字母行出现的百分比和计数
- javascript - 在中间件中调度 redux 操作会导致意外行为
- node.js - Express-session - 会话的并发修改
- android - 三星galaxy s7上的Android studio Camera Access,图像模糊
- javascript - 带有剃须刀页面的动态 javascript
- matlab - MATLAB水平的sobel滤波器