Python 脚本中有多个 SIGTERM 处理程序 - 谁应该调用 sys.exit()?
More than one SIGTERM handler in a Python script - who should call 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 之后都会正常退出。当我 运行 this 和 crtl-c 时,只打印“B”。
一般来说,在这种情况下,who 或 what 应该调用 sys.exit()
- 两个实例都应该调用吗?
signal 的 Python 文档仅说明当您多次为同一信号设置处理程序时会发生什么:
A handler for a particular signal, once set, remains installed until it is explicitly reset
和
[when calling signal.signal
] The previous signal handler will be returned
这似乎意味着,就像 POSIX 信号一样,一个进程一次只能有一个给定信号的处理程序。
我们可以在您的程序中添加一些语句来显示 signal.signal
returns(在 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>
,然后设置为 a
实例中的 disconnect
函数,然后设置为 disconnect
实例中的 disconnect
函数b
实例,后者是在传递信号时调用的实例。
如果你想在接收到 SIGINT 时退出,并且 运行 在退出前有多个函数,一种方法是调用以下命令(这将禁止打印回溯和 KeyboardInterrupt
消息):
signal.signal(signal.SIGINT, lambda *args: sys.exit())
然后使用atexit.register注册每个函数。
假设我有以下脚本:
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 之后都会正常退出。当我 运行 this 和 crtl-c 时,只打印“B”。
一般来说,在这种情况下,who 或 what 应该调用 sys.exit()
- 两个实例都应该调用吗?
signal 的 Python 文档仅说明当您多次为同一信号设置处理程序时会发生什么:
A handler for a particular signal, once set, remains installed until it is explicitly reset
和
[when calling
signal.signal
] The previous signal handler will be returned
这似乎意味着,就像 POSIX 信号一样,一个进程一次只能有一个给定信号的处理程序。
我们可以在您的程序中添加一些语句来显示 signal.signal
returns(在 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>
,然后设置为 a
实例中的 disconnect
函数,然后设置为 disconnect
实例中的 disconnect
函数b
实例,后者是在传递信号时调用的实例。
如果你想在接收到 SIGINT 时退出,并且 运行 在退出前有多个函数,一种方法是调用以下命令(这将禁止打印回溯和 KeyboardInterrupt
消息):
signal.signal(signal.SIGINT, lambda *args: sys.exit())
然后使用atexit.register注册每个函数。