如何获取我没有为其创建对象的子进程的pid?即
myProc = Popen(["sleep","30"])
vs
Popen(["sleep","30"])
如果我在发送终止信号后没有轮询()或等待(),我发现它们会变成僵尸进程。在我的脚本中的某个点上,我想找到我的脚本是其父项的所有子进程,并向它们发送信号或轮询它们。这在python中可能吗?它有可能吗?
答案 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
注意:
psutil
仅显示一个僵尸进程,其余部分在最后一次Popen()
电话中显示psutil
提供针对pid
reuse的保护,但在所有情况下都不是100%可靠 - 在您的情况下检查它是否足够(否则,请使用上述不依赖的方法)孩子的pid
)。