如何使用子进程模块杀死(或避免)僵尸进程

Dav*_*ave 51 python subprocess

当我使用子进程模块从另一个python脚本中启动python脚本时,子进程"完成"时会创建一个僵尸进程.除非我杀死我的父python进程,否则我无法终止此子进程.

有没有办法杀死子进程而不杀死父进程?我知道我可以通过使用wait()来实现这一点,但我需要使用no_wait()运行我的脚本.

Dav*_*yan 22

不使用Popen.communicate()call()将导致僵尸进程.

如果您不需要输出命令,可以使用subprocess.call():

>>> import subprocess
>>> subprocess.call(['grep', 'jdoe', '/etc/passwd'])
0
Run Code Online (Sandbox Code Playgroud)

如果输出很重要,您应该使用Popen()communicate()获取stdout和stderr.

>>> from subprocess import Popen, PIPE
>>> process = Popen(['ls', '-l', '/tmp'], stdout=PIPE, stderr=PIPE)
>>> stdout, stderr = process.communicate()
>>> stderr
''
>>> print stdout
total 0
-rw-r--r-- 1 jdoe jdoe 0 2010-05-03 17:05 bar
-rw-r--r-- 1 jdoe jdoe 0 2010-05-03 17:05 baz
-rw-r--r-- 1 jdoe jdoe 0 2010-05-03 17:05 foo
Run Code Online (Sandbox Code Playgroud)

  • 使用`Popen.poll()`,您可以检查进程是否已完成,然后您可以使用`communic`.这样就可以保持并发性. (5认同)
  • 谢谢你的评论。不幸的是,在产生新的进程之前,通信会等待进程完成。我需要并行运行多个进程。 (2认同)
  • call()等待进程完成.我认为OP希望在它们运行时产生进程并在父进程中执行其他操作. (2认同)

tzo*_*zot 20

僵尸进程不是一个真正的过程; 它只是进程表中的剩余条目,直到父进程请求子进程返回代码.实际流程已结束,不需要其他资源,只需要表示流程表条目.

我们可能需要有关您运行的流程的更多信息才能真正提供更多帮助.

但是,如果您的Python程序知道子进程何时结束(例如,通过到达子stdout数据的末尾),那么您可以安全地调用process.wait():

import subprocess

process= subprocess.Popen( ('ls', '-l', '/tmp'), stdout=subprocess.PIPE)

for line in process.stdout:
        pass

subprocess.call( ('ps', '-l') )
process.wait()
print "after wait"
subprocess.call( ('ps', '-l') )
Run Code Online (Sandbox Code Playgroud)

示例输出:

$ python so2760652.py
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S   501 21328 21326  0  80   0 -  1574 wait   pts/2    00:00:00 bash
0 S   501 21516 21328  0  80   0 -  1434 wait   pts/2    00:00:00 python
0 Z   501 21517 21516  0  80   0 -     0 exit   pts/2    00:00:00 ls <defunct>
0 R   501 21518 21516  0  80   0 -   608 -      pts/2    00:00:00 ps
after wait
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S   501 21328 21326  0  80   0 -  1574 wait   pts/2    00:00:00 bash
0 S   501 21516 21328  0  80   0 -  1467 wait   pts/2    00:00:00 python
0 R   501 21519 21516  0  80   0 -   608 -      pts/2    00:00:00 ps
Run Code Online (Sandbox Code Playgroud)

否则,您可以将所有孩子保留在列表中,然后立即.poll返回其返回码.每次迭代后,请记住从列表中删除返回代码不同的子代None(即已完成的代码).

  • 如果可能的话,我会放弃2个! (2认同)

小智 15

如果删除子进程对象,使用del强制进行垃圾回收,这将导致删除子进程对象,然后失效的进程将在不终止解释器的情况下消失.您可以先在python命令行界面中尝试此操作.


ibz*_*ibz 6

如果你只是使用subprocess.Popen,你会没事的 - 这是如何:

import subprocess

def spawn_some_children():
    subprocess.Popen(["sleep", "3"])
    subprocess.Popen(["sleep", "3"])
    subprocess.Popen(["sleep", "3"])

def do_some_stuff():
    spawn_some_children()
    # do some stuff
    print "children went out to play, now I can do my job..."
    # do more stuff

if __name__ == '__main__':
    do_some_stuff()
Run Code Online (Sandbox Code Playgroud)

您可以使用.poll()Popen返回的对象来检查它是否完成(无需等待).如果它返回None,则孩子仍在运行.

确保你没有保留对Popen对象的引用 - 如果你这样做,它们将不会被垃圾收集,所以你最终会得到僵尸.这是一个例子:

import subprocess

def spawn_some_children():
    children = []
    children.append(subprocess.Popen(["sleep", "3"]))
    children.append(subprocess.Popen(["sleep", "3"]))
    children.append(subprocess.Popen(["sleep", "3"]))
    return children

def do_some_stuff():
    children = spawn_some_children()
    # do some stuff
    print "children went out to play, now I can do my job..."
    # do more stuff

    # if children finish while we are in this function,
    # they will become zombies - because we keep a reference to them
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,如果你想摆脱僵尸,你可以.wait()在每个孩子身上或.poll()直到结果不是None.

无论哪种方式都很好 - 要么不保留引用,要么使用.wait().poll().

  • [你有没有检查过,如果父母还活着,你的第一个例子不会产生僵尸?](http://stackoverflow.com/questions/2760652/how-to-kill-or-avoid-zombie-processes-with-subprocess -module#comment29817645_6236440) (4认同)

Pet*_*ter 5

一旦他们的进程对象被垃圾收集,python运行时负责摆脱僵尸进程.如果你看到僵尸躺在它周围意味着你保留了一个进程对象,而不是等待,轮询或终止它.

  • [一个简单的测试表明它在 Python 2 上不正确](https://gist.github.com/zed/7504999)。它似乎适用于 Python 3 (3认同)

Dan*_*ach 0

我不完全确定你的意思no_wait()。您的意思是您不能阻止等待子进程完成吗?假设是这样,我认为这会做你想要的:

os.wait3(os.WNOHANG)
Run Code Online (Sandbox Code Playgroud)