版本信息:

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

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

  • marker 1marker 2之间发送的CTRL-C将由异常处理程序处理(如预期).
  • marker 2marker 3之间发送的CTRL-C被忽略(仍然如预期的那样)
  • 处理marker 3后发送CTRL-C,但not将跳转到异常处理程序.相反,Python只是terminates immediately.

同时,考虑一下:

>>>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后忽略异常处理程序时.

推荐答案

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

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

original_sigint_handler = signal.getsignal(signal.SIGINT)

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

正如kindall在 comments 中所说,你可以用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)

Python-3.x相关问答推荐

在多个测试中维护和报告变量

如果行在所有上级索引中都为0,如何删除下级索引行?

按一列分组,如果日期列相同,则在数字列中填写缺少的值

visual studio代码窗口中未激活虚拟环境11

AddMultplicationEquality() 用于多个变量

在 string.find() 条件下加入两个 Dataframes

pytorch 中 mps 设备的 manual_seed

如何在python 3.10中将列表项(字符串类型)转换为模块函数

避免重复连续字符但不包括一个特定字符的正则表达式

通过附加/包含多个列表来创建 nDimensional 列表

如何准确测定cv2的结果.在BW/黑白图像中查找对象?

为什么 List 不能包含多种类型?

使用 python 正则表达式匹配日期

ValueError:预期的 2D 数组,得到 1D 数组:

将 args、kwargs 传递给 run_in_executor

为什么排序列表比未排序列表大

为什么在 Python 3 中实例的 __dict__ 的大小要小得多?

同步调用协程

首次使用后 zip 变量为空

在 PyCharm 中配置解释器:请使用不同的 SDK 名称