如何采用" python中的子进程

时间:2015-11-25 23:00:46

标签: python linux subprocess

如何获取我没有为其创建对象的子进程的pid?即

myProc = Popen(["sleep","30"])

vs

Popen(["sleep","30"])

如果我在发送终止信号后没有轮询()或等待(),我发现它们会变成僵尸进程。在我的脚本中的某个点上,我想找到我的脚本是其父项的所有子进程,并向它们发送信号或轮询它们。这在python中可能吗?它有可能吗?

2 个答案:

答案 0 :(得分:5)

您可以使用psutil查找父Python进程的子级。例如:

import psutil
import os
import subprocess

subprocess.Popen(['sleep', '30'])

parent_pid = os.getpid()
parent = psutil.Process(parent_pid)

for child in parent.children():
    print(child)    # do something here

打印:

psutil.Process(pid=16822, name='sleep')

从那里你可以轮询他们,杀死他们等等。

答案 1 :(得分:1)

通常,您不需要执行任何操作 - 当前subprocess实现维护活动的未引用Popen实例的全局列表,并且在创建新的Popen对象时,此列表为为每个进程调用enumerate和.poll()

因此,如果您没有对子流程的引用;它会自动等待(如果你有参考,那么自己打电话给.wait())。

如果子进程是通过其他方式创建的,那么您可以调用os.waitpid()来收集Unix上死子进程的退出状态:

while True:
    try:
        pid, status = os.waitpid(-1, os.WNOHANG) 
    except ChildProcessError:
        #  No more child processes exist
        break
    else:
        assert pid, "child process is still alive"

在POSIX.1-2001系统上,您可以调用signal(SIGCHLD, SIG_IGN)来自动收集孩子。

如果你想在父母去世时杀死所有孩子(发送信号);你可以use prctl PR_SET_PDEATHSIG on Linux。如果父母因任何原因而死亡,即使父母被SIGKILL杀死,它也会有效。

来自psutil

@ali_m' answer是一种便携式解决方案:

#!/usr/bin/env python
import gc
import subprocess
import time

import psutil


for _ in range(10):
    subprocess.Popen(['sleep', '1'])  # no reference
time.sleep(2)  # wait until they are dead
gc.collect()  # run garbage collection, to populate _active list
subprocess.Popen(['sleep', '1'])  # trigger _cleanup()

for i in range(2):
    for child in psutil.Process().children():  # immediate children
        print(child, child.status())
    if i == 0:
        time.sleep(2)

输出

psutil.Process(pid=31253, name='sleep') sleeping
psutil.Process(pid=31253, name='sleep') zombie

注意:

  1. psutil仅显示一个僵尸进程,其余部分在最后一次Popen()电话中显示
  2. psutil提供针对pid reuse的保护,但在所有情况下都不是100%可靠 - 在您的情况下检查它是否足够(否则,请使用上述不依赖的方法)孩子的pid)。