44

私は現在、シェルで実行されている専用サーバーのラッパーに取り組んでいます。ラッパーはサブプロセスを介してサーバープロセスを生成し、その出力を監視して反応します。

専用サーバーには、正常にシャットダウンするコマンドを明示的に指定する必要があります。したがって、CTRL-Cはサーバープロセスに到達してはなりません。

KeyboardInterrupt例外をキャプチャするか、PythonでSIGINTハンドラーを上書きしても、サーバープロセスは引き続きCTRL-Cを受け取り、すぐに停止します。

だから私の質問は:サブプロセスがCTRL-C / Control-C / SIGINTを受け取らないようにする方法は?

4

5 に答える 5

44

#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で作成されています。

于 2011-02-19T11:27:36.553 に答える
26

トリックを実行する他の回答のいくつかを組み合わせると、メインアプリに送信されたシグナルはサブプロセスに転送されません。

import os
from subprocess import Popen

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

Popen('whatever', preexec_fn = preexec)
于 2011-03-27T03:16:56.513 に答える
6

あなたはそれをウィンドウズと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)
于 2016-08-26T21:02:19.500 に答える
1

サブプロセスを生成する前に、 SIGINTを無視するように設定してみてください(後でデフォルトの動作にリセットしてください)。

それがうまくいかない場合は、ジョブ制御を読み、プロセスを独自のバックグラウンドプロセスグループに配置する方法を学ぶ必要があります。そうすれば^C、カーネルが最初にシグナルを送信することさえありません。 。(PythonではCヘルパーを記述しないと不可能な場合があります。)

この古い質問も参照してください。

于 2011-02-18T20:06:19.310 に答える
1

さまざまな試みを1時間行った後、これは私にとってはうまくいきます。

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

それは窓のための解決策です。

于 2020-08-01T17:59:07.563 に答える