繁体   English   中英

如何在python中“采用”子进程

[英]How to “adopt” a child process in python

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

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

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

我注意到,如果在发送终止信号后不对它们进行poll()或wait(),它们将成为僵尸进程。 在脚本的某个时刻,我想找到脚本作为其父级的所有子进程,并向它们发送信号或对其进行轮询。 这可能在python中吗? 有可能吗?

您可以使用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')

您可以从那里轮询,杀死它们等。

通常,您不需要执行任何操作-当前的subprocess实现维护活动的未引用Popen实例的全局列表,并且在创建新的Popen对象时,此列表将枚举,并为每个进程调用.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)来自动收割子代。

如果您想在父母去世时杀死所有孩子(发出信号); 您可以在Linux上使用prctl PR_SET_PDEATHSIG 如果父母因任何原因去世,它就可以工作,即使父母被SIGKILL杀死也可以。

psutil@ali_m的回答是一个便携的解决方案:

#!/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重用的保护,但并非在所有情况下都是100%可靠的-检查您的情况是否足够(否则,请使用上面一种不依赖child的pid )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM