将Python SIGINT重置为默认信号手

2024-10-06 12:45:28 发布

您现在位置:Python中文网/ 问答频道 /正文

版本信息:

  • 操作系统: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!')

我在玩这个游戏时观察到的情况:

  • CTRL-C标记1标记2之间发送的{}将由异常处理程序处理(如预期)。
  • CTRL-C标记2标记3之间发送的{}将被忽略(仍然如预期的那样)
  • CTRL-C在处理标记3之后发送,但将跳转到异常处理程序。相反,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后忽略异常处理程序的情况下。


Tags: 标记importdefault处理程序signaltimesleepmarker
1条回答
网友
1楼 · 发布于 2024-10-06 12:45:28

Python安装自己的SIGINT处理程序以引发KeyboardInterrupt异常。将信号设置为SIG_DFL不会还原该处理程序,而是还原系统本身的“标准”处理程序(它终止解释器)。

完成后,必须存储原始处理程序并还原该处理程序:

original_sigint_handler = signal.getsignal(signal.SIGINT)

# Then, later...
signal.signal(signal.SIGINT, original_sigint_handler)

正如评论中恰如其分地说的,您可以将其表示为context manager

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)

相关问题 更多 >