如何 "adopt" 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 object ,这个列表是枚举的,每个进程都会调用 .poll()
。
因此,如果您没有对子流程的引用;它会自动等待您(如果您确实有参考,请自己致电 .wait()
)。
如果 child 进程是通过其他方式创建的,那么您可以调用 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)
来自动获得 children。
如果你想在parent死亡时杀死所有children(发送信号);你可以 use prctl
PR_SET_PDEATHSIG
on Linux。如果 parent 因任何原因死亡,它会起作用,即,即使 parent 被 SIGKILL
.
杀死,它也会起作用
psutil
from 是一个可移植的解决方案:
#!/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% 可靠——检查它是否足够适合你的情况(否则,使用上面的方法不依赖 child 的 pid
)。
如何获取我没有为其创建对象的子进程的 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 object ,这个列表是枚举的,每个进程都会调用 .poll()
。
因此,如果您没有对子流程的引用;它会自动等待您(如果您确实有参考,请自己致电 .wait()
)。
如果 child 进程是通过其他方式创建的,那么您可以调用 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)
来自动获得 children。
如果你想在parent死亡时杀死所有children(发送信号);你可以 use prctl
PR_SET_PDEATHSIG
on Linux。如果 parent 因任何原因死亡,它会起作用,即,即使 parent 被 SIGKILL
.
psutil
from
#!/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% 可靠——检查它是否足够适合你的情况(否则,使用上面的方法不依赖 child 的pid
)。