如何在python中干净地杀死子进程 [英] How to cleanly kill subprocesses in python

查看:147
本文介绍了如何在python中干净地杀死子进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在使用python进程来管理长时间运行的python子进程.子进程有时需要被杀死.kill命令不会完全杀死该进程,只会使其消失.

We are using a python process to manage long running python subprocesses. Subprocesses occasionally need to be killed. The kill command does not completely kill the process, only makes it defunct.

运行以下脚本演示了此行为.

Running the following script demonstrates this behaviour.

import subprocess
p = subprocess.Popen(['sleep', '400'], stdout=subprocess.PIPE, shell=False)

p = subprocess.Popen('sleep 400', stdout=subprocess.PIPE, shell=True)

将创建一个子流程.

p.terminate() 
p.kill()

对该过程没有任何作用.由 ps aux演示|grep sleep

does nothing to the process. Demonstrated by ps aux | grep sleep

$ ps aux| grep 'sleep'
User       8062  0.0  0.0   7292   764 pts/7    S    14:53   0:00 sleep 400

该进程尚未被终止/已终止.将 subprocess.call()函数与'kill' pid 作为参数一起使用,将发出kill命令.

The process has not been killed/made defunct. Using the subprocess.call() function with 'kill' and pid as arguments will issue the kill command.

subprocess.call(['kill', str(p.pid)])

这将终止该进程,但现在已终止.

This will kill the process but it is now defunct.

$ ps aux | grep 'sleep'
User       8062  0.0  0.0      0     0 pts/7    Z+   14:51   0:00 [sleep] <defunct>

如果队列运行时间足够长,它将最终达到其最大进程数,还是最终获得已经失效的进程并变得正常?

If the queue is running long enough will it eventually reach its maximum number of processes, or will it eventually reap the defunct processes and be fine?

如果答案是前者,那么如何在不终止父进程的情况下处理python中已失效的进程?

If the answer is the former, how can I handle defunct processes in python without killing the parent process?

是否有更好的杀死进程的方法?

Is there a better way of killing processes?

推荐答案

这里有2个主要问题:

第一个问题:如果您使用的是 shell = True ,那么您将杀死运行进程的 shell ,而不是进程本身.父进程被杀死后,子进程将失效/不会立即被终止.

First issue: If you're using shell=True, so you're killing the shell running the process, not the process itself. With its parent killed, the child process goes defunct / isn't killed immediately.

在您的情况下,您使用的不是内置的 sleep ,因此您可以删除 shell = True Popen 将产生实际的进程ID: p.terminate()将起作用.

In your case, you're using sleep which is not built-in, so you could drop shell=True, and Popen would yield the actual process id: p.terminate() would work.

您可以(并且应该)在大多数情况下避免使用 shell = True ,即使它需要额外的python编码工作(将2个命令一起使用,重定向输入/输出,所有这些情况都可以)可以由一个或几个 Popen 没有 shell = True 很好地处理.

You can (and you should) avoid shell=True most of the time, even if it requires extra python coding effort (piping 2 commands together, redirecting input/output, all those cases can be nicely handled by one or several Popen without shell=True.

(第二个问题),如果该修复程序结束后该进程仍然无效,则可以调用 p.wait()(来自

And (second issue) if the process is still defunct when terminating after that fix, you could call p.wait() (from this question). Seems that calling terminate isn't enough. The Popen object needs to be garbage collected.

这篇关于如何在python中干净地杀死子进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆