rob*_*ert 40 python subprocess signals sigint keyboardinterrupt
我目前正在为shell中运行的专用服务器开发包装器.包装器通过子进程生成服务器进程,并观察并响应其输出.
必须明确地为专用服务器提供一个命令才能正常关闭.因此,CTRL-C不得访问服务器进程.
如果我捕获KeyboardInterrupt异常或覆盖python中的SIGINT处理程序,服务器进程仍然会收到CTRL-C并立即停止.
所以我的问题是:如何防止子进程接收CTRL-C/Control-C/SIGINT?
rob*_*ert 39
#python IRC-Channel(Freenode)中的某个人通过指出subprocess.Popen (...)的preexec_fn参数来帮助我:
如果preexec_fn设置为可调用对象,则在执行子进程之前,将在子进程中调用此对象.(仅限Unix)
因此,以下代码解决了该问题(仅限UNIX):
import subprocess
import signal
def preexec_function():
# Ignore the SIGINT signal by setting the handler to the standard
# signal handler SIG_IGN.
signal.signal(signal.SIGINT, signal.SIG_IGN)
my_process = subprocess.Popen(
["my_executable"],
preexec_fn = preexec_function
)
Run Code Online (Sandbox Code Playgroud)
注意:实际上不会阻止信号到达子进程.相反,上面的preexec_fn会覆盖信号的默认处理程序,以便忽略该信号.因此,如果子进程再次覆盖SIGINT处理程序,则此解决方案可能无效.
另一个注意事项:此解决方案适用于各种子进程,即它不仅限于用Python编写的子进程.例如,我正在编写包装器的专用服务器实际上是用Java编写的.
Mar*_*ota 24
结合其他一些可以解决问题的答案 - 没有信号发送到主应用程序将被转发到子进程.
import os
from subprocess import Popen
def preexec(): # Don't forward signals.
os.setpgrp()
Popen('whatever', preexec_fn = preexec)
Run Code Online (Sandbox Code Playgroud)
小智 6
你可以做这样的事情,使其在 windows 和 unix 中工作:
import subprocess
import sys
def pre_exec():
# To ignore CTRL+C signal in the new process
signal.signal(signal.SIGINT, signal.SIG_IGN)
if sys.platform.startswith('win'):
#https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
#CREATE_NEW_PROCESS_GROUP=0x00000200 -> If this flag is specified, CTRL+C signals will be disabled
my_sub_process=subprocess.Popen(["executable"], creationflags=0x00000200)
else:
my_sub_process=subprocess.Popen(["executable"], preexec_fn = pre_exec)
Run Code Online (Sandbox Code Playgroud)
经过一个小时的各种尝试,这对我有用:
process = subprocess.Popen(["someprocess"], creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP)
Run Code Online (Sandbox Code Playgroud)
这是 Windows 的解决方案。