我的Python脚本使用signal模块拦截SIGINT信号以防止过早退出,但是这个信号会传递给我使用Popen打开的子进程。有没有办法防止将此信号传递给子进程,以便用户按下ctrl-c时子进程也不会被意外退出?
我的Python脚本使用signal模块拦截SIGINT信号以防止过早退出,但是这个信号会传递给我使用Popen打开的子进程。有没有办法防止将此信号传递给子进程,以便用户按下ctrl-c时子进程也不会被意外退出?
当启动子进程时,会继承信号处理程序。因此,如果您使用signal模块来忽略SIGINT信号 (signal.signal(signal.SIGINT, signal.SIG_IGN)
),那么您的子进程也会自动忽略SIGINT信号。
但需要注意两个重要的限制:
因此,如果您需要自定义处理SIGINT而不仅仅是忽略它,您可能需要在生成子进程时暂时忽略SIGINT,然后(重新)设置自定义信号处理程序。
如果您试图捕获SIGINT并设置标志以便在安全点退出而不是立即退出,请记住,在到达该安全点时,您的代码将必须手动清理其子孙进程,因为您的子进程和任何由它启动的进程都将忽略SIGINT信号。
tty
模块重新分配ctrl-c的作用,该模块允许您操纵信号的分配。请注意,除非将它们在修改之前恢复,否则它们将在整个会话期间持续存在,甚至在程序退出后也是如此。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)
对于 Python 2 代码库:子进程已经损坏。
正确的方法是
import subprocess32 as subprocess
请查看subprocess32
这是Python 3子进程模块的回溯版本,可用于Python 2。该代码尚未在Windows或其他非POSIX平台上进行测试。