我的 python 脚本使用信号处理模块拦截 SIGINT 信号以防止过早退出,但是这个信号被传递给我用 Popen 打开的子进程。是否有某种方法可以防止将此信号传递给子进程,以便在用户按下 ctrl-c 时它也不会过早退出?
问问题
4991 次
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
这是用于 Python 2 的 Python 3 子进程模块的反向移植。此代码尚未在 Windows 或其他非 POSIX 平台上进行测试。
于 2021-01-11T11:16:20.293 回答