简体   繁体   English

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

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

How can I get the pid of a child processes that I didn't create an object for? 我如何获取未为其创建对象的子进程的pid? ie

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

vs

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

I've noticed they become zombie processes if I don't poll() or wait() on them after sending a termination signal. 我注意到,如果在发送终止信号后不对它们进行poll()或wait(),它们将成为僵尸进程。 At a point in my script I would like to find all child processes that my script is a parent of and send them a signal or poll them. 在脚本的某个时刻,我想找到脚本作为其父级的所有子进程,并向它们发送信号或对其进行轮询。 Is this possible in python? 这可能在python中吗? Is it possible at all? 有可能吗?

You could use psutil to find the children of your parent Python process. 您可以使用psutil查找父Python进程的子进程。 For example: 例如:

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

Prints: 印刷品:

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

From there you could poll them, kill them etc. 您可以从那里轮询,杀死它们等。

Normally, you don't need to do anything -- the current subprocess implementation maintains a global list of active unreferenced Popen instances and when a new Popen object is created, this list is enumerate and .poll() is called for each process. 通常,您不需要执行任何操作-当前的subprocess实现维护活动的未引用Popen实例的全局列表,并且在创建新的Popen对象时,此列表将枚举,并为每个进程调用.poll()

Thus if you don't have a reference to the subprocess; 因此,如果您没有对子流程的引用; it is waited for you automatically (and if you do have a reference then call .wait() yourself). 它会自动等待您(如果您有引用,则可以自己调用.wait() )。

If child processes are created by other means then you could call os.waitpid() to collect exit statuses of dead subprocesses on Unix: 如果子进程是通过其他方式创建的,则可以调用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"

On POSIX.1-2001 systems, you could call signal(SIGCHLD, SIG_IGN) to reap children automatically instead. 在POSIX.1-2001系统上,您可以调用signal(SIGCHLD, SIG_IGN)来自动收割子代。

If you want to kill all children (send a signal) when a parent dies; 如果您想在父母去世时杀死所有孩子(发出信号); you could use prctl PR_SET_PDEATHSIG on Linux . 您可以在Linux上使用prctl PR_SET_PDEATHSIG It works if the parent dies for any reason ie, it works even if the parent is killed by SIGKILL . 如果父母因任何原因去世,它就可以工作,即使父母被SIGKILL杀死也可以。

psutil from @ali_m' answer is a portable solution: 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)

Output 输出量

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

Note: 注意:

  1. psutil shows only one zombie process, the rest are reaped in the last Popen() call psutil仅显示一个僵尸进程,其余的将在最后一个Popen()调用中获得
  2. psutil provides a protection against pid reuse but it is not 100% reliable in all cases -- check whether it is enough in your case (otherwise, use one the methods above that do not rely on child's pid ). psutil提供了防止pid重用的保护,但并非在所有情况下都是100%可靠的-检查您的情况是否足够(否则,请使用上面一种不依赖child的pid )。

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

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