将Python SIGINT重置为默认信号处理程序

ƘɌỈ*_*ƬƠƑ 11 python windows signals python-3.x

版本信息:

  • 操作系统: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!')
Run Code Online (Sandbox Code Playgroud)

我在玩这个时就观察到了什么:

  • 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
Run Code Online (Sandbox Code Playgroud)

所以最初,虽然信号处理程序被认为是默认的信号处理程序,但它似乎是一个与定义的处理程序不同的处理程序SIG_DFL.

如果有人能够对此有所了解,特别是在将信号处理程序恢复到SIG_DFL后忽略异常处理程序.

Fré*_*idi 18

Python安装自己的SIGINT处理程序以引发KeyboardInterrupt异常.将信号设置为SIG_DFL不会恢复该处理程序,而是系统本身的"标准"处理程序(终止解释程序).

您必须存储原始处理程序并在完成后恢复该处理程序:

original_sigint_handler = signal.getsignal(signal.SIGINT)

# Then, later...
signal.signal(signal.SIGINT, original_sigint_handler)
Run Code Online (Sandbox Code Playgroud)

正如评论中所说的那样,您可以将其表达为上下文管理器:

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)
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用它:

# 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)
Run Code Online (Sandbox Code Playgroud)

  • 请注意,默认处理程序始终可用作`signal.default_int_handler`. (6认同)
  • 如果你在 `try/finally` 中省略了 ` except:` 块,python 就会冒泡异常 (4认同)
  • 另请注意,“signal.signal()”返回前一个信号处理程序,因此不需要单独调用“signal.getsignal()”。 (3认同)