如何阻止SIGINT传递给python中的子进程?

时间:2010-07-12 21:57:59

标签: python subprocess signals intercept sigint

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

3 个答案:

答案 0 :(得分:15)

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

但有两个重要的警告:

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

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

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

答案 1 :(得分:2)

您可以使用tty模块重新分配ctrl-c的角色,该模块允许您操作信号的分配。但是,请注意,除非你在修改它们之前将它们放回原来的状态,否则即使程序退出,它们仍将持续进行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)

答案 2 :(得分:0)

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

正确的是

import subprocess32 as subprocess

subprocess32

<块引用>

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