我们正在使用python进程来管理长时间运行的python子进程。偶尔需要杀死子程序。 kill命令不会完全终止进程,只会使其失效。
运行以下脚本演示了此行为。
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
$ 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命令。
subprocess.call(['kill', str(p.pid)])
这会扼杀这个过程但现在已经不存在了。
$ ps aux | grep 'sleep'
User 8062 0.0 0.0 0 0 pts/7 Z+ 14:51 0:00 [sleep] <defunct>
如果队列运行的时间足够长,它最终会达到最大进程数,还是最终会收到已解散的进程并且没问题呢?
如果答案是前者,如何在不杀死父进程的情况下处理python中的defunct进程?
有没有更好的方法来杀死进程?
答案 0 :(得分:7)
这里有两个主要问题:
第一个问题:如果你正在使用shell=True
,那么你就是要杀死运行流程的 shell ,而不是流程本身。随着父母被杀,孩子的过程就会不复存在,也不会立即被杀死。
在您的情况下,您使用的是非内置的sleep
,因此您可以删除shell=True
,Popen
会产生实际的进程ID:{{ 1}}会起作用。
你可以(并且你应该)在大多数时候避免使用p.terminate()
,即使它需要额外的python编码工作(将2个命令组合在一起,重定向输入/输出,所有这些情况都可以很好地处理一个或者多个shell=True
没有 Popen
。
并且(第二期)如果在该修复后终止该流程仍然无效,您可以致电shell=True
(来自this问题)。似乎调用p.wait()
还不够。 terminate
对象需要进行垃圾回收。
答案 1 :(得分:2)
您应该在终止子进程后调用p.wait()
- 清除进程表。这应该删除僵尸进程(defunct
状态)