Python:如何防止子进程接收CTRL-C / Control-C / SIGINT

时间:2011-02-18 19:39:39

标签: python subprocess signals sigint keyboardinterrupt

我目前正致力于在shell中运行的专用服务器的包装器。包装器通过子进程生成服务器进程,并观察并响应其输出。

必须明确地为专用服务器提供一个命令才能正常关闭。因此,CTRL-C不得访问服务器进程。

如果我捕获KeyboardInterrupt异常或覆盖python中的SIGINT处理程序,服务器进程仍会收到CTRL-C并立即停止。

所以我的问题是: 如何防止子进程接收CTRL-C / Control-C / SIGINT?

5 个答案:

答案 0 :(得分:37)

#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
)

注意:实际上不会阻止信号到达子进程。相反,上面的 preexec_fn 会覆盖信号的默认处理程序,以便忽略该信号。因此,如果子进程再次覆盖 SIGINT 处理程序,则此解决方案可能不起作用。

另一个注意事项:此解决方案适用于所有类型的子进程,即它也不限于用Python编写的子进程。例如,我正在编写包装器的专用服务器实际上是用Java编写的。

答案 1 :(得分:22)

结合其他一些可以解决问题的答案 - 发送到主应用程序的信号不会转发到子流程。

import os
from subprocess import Popen

def preexec(): # Don't forward signals.
    os.setpgrp()

Popen('whatever', preexec_fn = preexec)

答案 2 :(得分:2)

你可以做这样的事情,使它在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)

答案 3 :(得分:1)

在生成子进程之前尝试将SIGINT设置为忽略(之后将其重置为默认行为)。

如果这不起作用,您需要阅读job control并了解如何将进程放入其自己的后台进程组中,以便 ^ C 不会t甚至导致内核首先向它发送信号。 (如果不编写C语言助手,可能无法在Python中使用。)

另见this older question

答案 4 :(得分:0)

经过一个小时的尝试,这对我有用:

process = subprocess.Popen(["someprocess"], creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP)

这是Windows的解决方案。