重置Python SIGINT为默认信号处理器
版本信息:
- 操作系统:Windows 7
- Python版本:3.3.5
下面是一段我在测试的小代码。我的目的是在某段代码执行时忽略按下的CTRL-C
,执行完后再恢复CTRL-C
的正常功能。
import signal
import time
try:
# marker 1
print('No signal handler modifications yet')
print('Sleeping...')
time.sleep(10)
# marker 2
signal.signal(signal.SIGINT, signal.SIG_IGN)
print('Now ignoring CTRL-C')
print('Sleeping...')
time.sleep(10)
# marker 3
print('Returning control to default signal handler')
signal.signal(signal.SIGINT, signal.SIG_DFL)
print('Sleeping...')
time.sleep(10)
except KeyboardInterrupt:
print('Ha, you pressed CTRL-C!')
在测试过程中,我观察到以下几点:
- 在标记1和标记2之间按下的
CTRL-C
会被异常处理程序处理(这是预期的结果)。 - 在标记2和标记3之间按下的
CTRL-C
会被忽略(这也是预期的结果)。 - 在标记3之后按下的
CTRL-C
会被处理,但不会跳转到异常处理程序。相反,Python会立即终止。
另外,请考虑以下内容:
>>>import signal
>>>signal.getsignal(signal.SIGINT)
<built-in function default_int_handler>
>>> signal.getsignal(signal.SIGINT) is signal.SIG_DFL
False
>>> signal.signal(signal.SIGINT, signal.SIG_DFL)
<built-in function default_int_handler>
>>> signal.getsignal(signal.SIGINT) is signal.SIG_DFL
True
所以最开始,当信号处理程序被视为默认信号处理程序时,它似乎与SIG_DFL
定义的处理程序不同。
如果有人能对此提供一些解释,特别是在将信号处理程序恢复为SIG_DFL后,为什么异常处理程序会被忽略。
1 个回答
42
Python会安装自己的
所以,你需要先保存原来的处理器,然后在完成操作后再把它恢复回来:
original_sigint_handler = signal.getsignal(signal.SIGINT)
# Then, later...
signal.signal(signal.SIGINT, original_sigint_handler)
正如kindall在评论中所说的,你可以把这个过程写成一个上下文管理器:
from contextlib import contextmanager
@contextmanager
def sigint_ignored():
original_sigint_handler = signal.getsignal(signal.SIGINT)
signal.signal(signal.SIGINT, signal.SIG_IGN)
try:
print('Now ignoring CTRL-C')
yield
except:
raise # Exception is dropped if we don't reraise it.
finally:
print('Returning control to default signal handler')
signal.signal(signal.SIGINT, original_sigint_handler)
你可以这样使用它:
# marker 1
print('No signal handler modifications yet')
print('Sleeping...')
time.sleep(10)
# marker 2
with sigint_ignored():
print('Sleeping...')
time.sleep(10)
# marker 3
print('Sleeping...')
time.sleep(10)