终止正在运行的子进程调用

16

我在Python中使用subprocess启动程序。

有时候程序可能会冻结,这是我无法控制的。我能从启动它的命令行执行以下操作:CtrlEsc 快速停止该程序。

有没有办法通过subprocess模块模拟这个过程?我正在使用subprocess.Popen(cmd, shell=True) 启动这个程序。

6个回答

25

嗯,subprocess.Popen()返回的对象有几种方法可能会有用:Popen.terminate()Popen.kill(),分别发送SIGTERMSIGKILL

例如...

import subprocess
import time

process = subprocess.Popen(cmd, shell=True)
time.sleep(5)
process.terminate()

...会在五秒后终止该进程。

或者,您可以使用os.kill()发送其他信号(如SIGINT)来模拟按下CTRL-C,...

import subprocess
import time
import os
import signal

process = subprocess.Popen(cmd, shell=True)
time.sleep(5)
os.kill(process.pid, signal.SIGINT)

4
在Windows系统中,“kill = terminate”和信号(signals)的工作方式不同。 - jfs
1
这个答案缺少对 process.wait() 的调用 — https://dev59.com/BrLma4cB1Zd3GeqPZl6h - Clément

19

2
最好在直接杀死它之前尝试终止。 - Gewthen
3
尝试终止并杀死子进程,但它仍在运行! - hungryWolf
1
那可能是因为 shell=True。 - Jean-François Fabre
请注意,在杀死进程后,除非您等待()该进程,否则会创建僵尸进程,ResourceWarning: subprocess 512574 is still running https://dev59.com/BrLma4cB1Zd3GeqPZl6h - Clément

0

您的问题不是很清楚,但如果我假设您即将启动一个进程并且该进程会变成僵尸进程,而您希望能够在脚本的某个状态下控制它。如果是这种情况,我建议您采取以下措施:

p = subprocess.Popen([cmd_list], shell=False)

这不是通过shell的最佳方式。 我建议您使用shell=False,这样您的风险会更小。

# Get the process id & try to terminate it gracefuly
pid = p.pid
p.terminate()

# Check if the process has really terminated & force kill if not.
try:
    os.kill(pid, 0)
    p.kill()
    print "Forced kill"
except OSError, e:
    print "Terminated gracefully"

  • p.pid是Popen实例的一个属性,而不是方法。
  • OSError什么时候被引发?即使是简单的Popen调用(subprocess.Popen("ls", shell=False)),我似乎也无法进入except语句。
- bergercookie
没错,pid 是一个�性,那应该是打字错误了。对� OSError 异常,在 os.kill(pid, 0) 步骤中如� pid ��存在,则会抛出异常 - p.terminate() �功终止了 pid 😉 - ScotchAndSoda
需要同时使用 os.killp.kill 吗?一个不够吗? - leoOrion

0

以下命令对我有用

os.system("pkill -TERM -P %s"%process.pid)

0
您可以使用两个信号来终止正在运行的子进程调用,即signal.SIGTERM和signal.SIGKILL;例如:
import subprocess
import os
import signal
import time
..
process = subprocess.Popen(..)
..
# killing all processes in the group
os.killpg(process.pid, signal.SIGTERM)
time.sleep(2)
if process.poll() is None:  # Force kill if process is still alive
    time.sleep(3)
    os.killpg(process.pid, signal.SIGKILL)

你可以使用带有超时的wait(2)代替sleep(2)+poll,这样如果进程快速退出就不会浪费两秒钟。此外,你可以使用process.terminateprocess.kill代替os.killpg - Clément

-1

尝试将您的subprocess.Popen调用包装在try except块中。根据您的进程挂起的原因,您可能能够干净地退出。以下是您可以检查的异常列表:Python 3 - 异常处理


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接