385

次のコマンドでサブプロセスを起動しています。

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)

しかし、私が使用して殺そうとすると:

p.terminate()

また

p.kill()

コマンドはバックグラウンドで実行され続けるので、どうすれば実際にプロセスを終了できるのでしょうか。

次のコマンドを実行すると、次のことに注意してください。

p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)

を発行すると正常に終了しp.terminate()ます。

4

10 に答える 10

487

プロセスグループを使用して、グループ内のすべてのプロセスに信号を送信できるようにします。そのためには、生成された/子プロセスの親プロセス(この場合はシェル)にセッションIDをアタッチする必要があります。これにより、プロセスのグループリーダーになります。したがって、シグナルがプロセスグループリーダーに送信されると、このグループのすべての子プロセスに送信されます。

コードは次のとおりです。

import os
import signal
import subprocess

# The os.setsid() is passed in the argument preexec_fn so
# it's run after the fork() and before  exec() to run the shell.
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
                       shell=True, preexec_fn=os.setsid) 

os.killpg(os.getpgid(pro.pid), signal.SIGTERM)  # Send the signal to all the process groups
于 2011-01-25T09:07:49.523 に答える
116
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
p.kill()

p.kill()シェルプロセスを強制終了し、cmd実行中です。

私はこれを次のようにして便利な修正を見つけました:

p = subprocess.Popen("exec " + cmd, stdout=subprocess.PIPE, shell=True)

これにより、cmdは、強制終了されない子プロセスをシェルに起動させる代わりに、シェルプロセスを継承します。 p.pidその場合、cmdプロセスのIDになります。

p.kill()動作するはずです。

しかし、これがあなたのパイプにどのような影響を与えるかはわかりません。

于 2012-10-30T16:01:25.313 に答える
76

psutilを使用できる場合、これは完全に機能します。

import subprocess

import psutil


def kill(proc_pid):
    process = psutil.Process(proc_pid)
    for proc in process.children(recursive=True):
        proc.kill()
    process.kill()


proc = subprocess.Popen(["infinite_app", "param"], shell=True)
try:
    proc.wait(timeout=3)
except subprocess.TimeoutExpired:
    kill(proc.pid)
于 2014-08-05T09:07:15.487 に答える
34

私はそれを使用してそれを行うことができます

from subprocess import Popen

process = Popen(command, shell=True)
Popen("TASKKILL /F /PID {pid} /T".format(pid=process.pid))

cmd.exeそれは私が命令したプログラムとを殺しました。

(Windowsの場合)

于 2013-07-12T12:24:49.113 に答える
16

shell=Trueシェルが子プロセスであり、コマンドがその子である場合。したがって、シェルを強制終了するSIGTERMSIGKILL、その子プロセスを強制終了することはできません。そのための良い方法を覚えていません。私が考えることができる最善の方法は、を使用するshell=Falseことです。そうしないと、親シェルプロセスを強制終了すると、無効なシェルプロセスが残ります。

于 2011-01-25T04:22:40.673 に答える
11

これらの答えはどれも私にはうまくいきませんでしたので、私はうまくいったコードを残しました。私の場合、でプロセスを強制終了してリターンコード.kill()を取得した後でも、プロセスは終了しませんでした。.poll()

subprocess.Popen ドキュメントに従う:

「...適切に動作するアプリケーションをクリーンアップするには、子プロセスを強制終了して通信を終了する必要があります...」

proc = subprocess.Popen(...)
try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

私の場合、proc.communicate()を呼び出した後、私は行方不明でしたproc.kill()。これにより、プロセスstdin、stdout ...がクリーンアップされ、プロセスが終了します。

于 2018-02-28T21:22:09.487 に答える
7

サイが言ったように、シェルは子であるため、信号はそれによってインターセプトされます-私が見つけた最良の方法は、shell = Falseを使用し、shlexを使用してコマンドラインを分割することです:

if isinstance(command, unicode):
    cmd = command.encode('utf8')
args = shlex.split(cmd)

p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

次に、p.kill()とp.terminate()が期待どおりに機能するはずです。

于 2011-01-25T04:53:19.237 に答える
3

グループ内のすべてのプロセスに信号を送信します

    self.proc = Popen(commands, 
            stdout=PIPE, 
            stderr=STDOUT, 
            universal_newlines=True, 
            preexec_fn=os.setsid)

    os.killpg(os.getpgid(self.proc.pid), signal.SIGHUP)
    os.killpg(os.getpgid(self.proc.pid), signal.SIGTERM)
于 2018-11-05T06:31:23.057 に答える
1

または+の非常に簡単な方法がありますPython 3.5(実際にテストされていますPython 3.8

import subprocess, signal, time
p = subprocess.Popen(['cmd'], shell=True)
time.sleep(5) #Wait 5 secs before killing
p.send_signal(signal.CTRL_C_EVENT)

次に、キーボード入力検出がある場合、またはこのような場合、コードはある時点でクラッシュする可能性があります。この場合、エラーが発生するコード/関数の行で、次を使用します。

try:
    FailingCode #here goes the code which is raising KeyboardInterrupt
except KeyboardInterrupt:
    pass

このコードが実行しているのは、実行中のプロセスに「CTRL+ C」シグナルを送信することです。これにより、プロセスが強制終了されます。

于 2020-11-28T11:38:58.943 に答える
0

私のために働いた解決策

if os.name == 'nt':  # windows
    subprocess.Popen("TASKKILL /F /PID {pid} /T".format(pid=process.pid))
else:
    os.kill(process.pid, signal.SIGTERM)
于 2022-01-31T11:46:36.007 に答える