16

我的 python 脚本使用信号处理模块拦截 SIGINT 信号以防止过早退出,但是这个信号被传递给我用 Popen 打开的子进程。是否有某种方法可以防止将此信号传递给子进程,以便在用户按下 ctrl-c 时它也不会过早退出?

4

3 回答 3

15

启动子进程时会继承信号处理程序,因此如果您使用信号模块忽略 SIGINT ( signal.signal(signal.SIGINT, signal.SIG_IGN)),那么您的子进程也会自动执行。

但是,有两个重要的警告:

  • 您必须在生成子进程之前设置忽略处理程序
  • 自定义信号处理程序被重置为默认处理程序,因为子进程将无权访问处理程序代码来运行它。

因此,如果您需要自定义处理 SIGINT 而不仅仅是忽略它,您可能希望在生成子进程时暂时忽略 SIGINT,然后(重新)设置自定义信号处理程序。

如果您试图捕获 SIGINT 并设置一个标志,以便您可以在安全点而不是立即退出,请记住,当您到达该安全点时,您的代码将不得不手动清理其后代,因为您的子进程和任何它启动的进程将忽略 SIGINT。

于 2010-09-17T00:42:51.837 回答
2

您可以使用该模块重新分配 ctrl-c 的角色tty,这允许您操纵信号的分配。但是请注意,除非您将它们恢复到修改它们之前的状态,否则它们将在 shell 的整个会话期间持续存在,即使在程序退出后也是如此。

这是一个简单的代码片段,可以帮助您开始存储您的旧 tty 设置,将 ctrl-c 重新分配给 ctrl-x,然后在退出时恢复您以前的 tty 设置。

import sys
import tty

# Back up previous tty settings
stdin_fileno = sys.stdin.fileno()
old_ttyattr = tty.tcgetattr(stdin_fileno)

try:
    print 'Reassigning ctrl-c to ctrl-x'

    # Enter raw mode on local tty
    tty.setraw(stdin_fileno)
    raw_ta = tty.tcgetattr(stdin_fileno)
    raw_ta[tty.LFLAG] |= tty.ISIG
    raw_ta[tty.OFLAG] |= tty.OPOST | tty.ONLCR

    # ^X is the new ^C, set this to 0 to disable it entirely
    raw_ta[tty.CC][tty.VINTR] = '\x18'  

    # Set raw tty as active tty
    tty.tcsetattr(stdin_fileno, tty.TCSANOW, raw_ta)

    # Dummy program loop
    import time
    for _ in range(5):
        print 'doing stuff'
        time.sleep(1)

finally:
    print 'Resetting ctrl-c'
    # Restore previous tty no matter what
    tty.tcsetattr(stdin_fileno, tty.TCSANOW, old_ttyattr)
于 2010-07-12T22:52:51.893 回答
0

对于 python 2 代码库:子进程已损坏。

正确的是

import subprocess32 as subprocess

subprocess32

这是用于 Python 2 的 Python 3 子进程模块的反向移植。此代码尚未在 Windows 或其他非 POSIX 平台上进行测试。

于 2021-01-11T11:16:20.293 回答