当父进程在循环中工作时,如何避免僵尸完成子进程
我正在寻找一个好的解决方案,以避免当父进程仍在工作时出现 ZOMBIE 子进程。例如,父级正在循环中工作并正在检查某些条件。如果条件满足,父进程运行子进程。
现在我编写了简单的 python 脚本:
File main.py:
#!/usr/bin/env python3
# coding=utf-8
import os
import psutil
import subprocess
import time
import signal
import setproctitle
def main():
python_venv = 'python3'
print(f"{__file__} - Run proc 1")
a1 = [python_venv, 'proc1.py']
string_do_wywolania_part2 = ['arg1' , 'arg2']
a2 = a1 + string_do_wywolania_part2
p = subprocess.Popen(a2, preexec_fn=os.setpgrp)
print(f"{__file__} - Run proc 2")
a1 = [python_venv, 'proc2.py']
string_do_wywolania_part2 = ['arg1' , 'arg2']
a2 = a1 + string_do_wywolania_part2
p = subprocess.Popen(a2, preexec_fn=os.setpgrp)
pid_id = os.getpid()
ppid_id = os.getppid()
print(f"{__file__} - pid_id : {pid_id} - ppid_id : {ppid_id}")
parent = psutil.Process(pid_id)
print(f"{__file__} : parent : {parent}")
t = 6
print(f"{__file__} - I am waiting {t} sec.")
time.sleep(t)
if __name__ == "__main__":
"call sub processes"
setproctitle.setproctitle('python3 - main')
main()
while True:
k = 1
pid_id = os.getpid()
parent = psutil.Process(pid_id)
print()
for child in parent.children(recursive=True): # or parent.children() for recursive=False
print(f'{__file__} - {child} = {child.status()}')
k +=1
time.sleep(5)
print(f'{__file__} : Finished main')
File proc1.py
#!/usr/bin/env python3
# coding=utf-8
import os
import sys
import time
import setproctitle
if __name__ == "__main__":
setproctitle.setproctitle('python3 - proc1')
pid = os.getpid()
ppid = os.getppid()
print(f"{__file__} - Process 1 is running")
print(f"{__file__} - pid : {pid} - ppid : {ppid}")
time.sleep(5)
print(f"{__file__} : Finished process 1 : {pid}")
sys.exit(0)
proc2.file:
#!/usr/bin/env python3
# coding=utf-8
import os
import sys
import time
import subprocess
import signal
import setproctitle
if __name__ == "__main__":
setproctitle.setproctitle('python3 - proc2')
print(f"{__file__} - Process 2 is running")
try:
pid = os.getpid()
ppid = os.getppid()
print(f"{__file__} - pid : {pid} - ppid : {ppid}")
print(f"{__file__} - Run proc 3")
python_venv = 'python3'
a1 = [python_venv, 'proc3.py']
string_do_wywolania_part2 = ['arg1' , 'arg2']
a2 = a1 + string_do_wywolania_part2
p = subprocess.Popen(a2, preexec_fn=os.setpgrp)
time.sleep(15)
except Exception as e:
print(e)
time.sleep(7)
print(f"{__file__} : Finished process 2 : {pid}")
sys.exit(0)
和最后一个 proc3.py
#!/usr/bin/env python3
# coding=utf-8
import os
import sys
import time
import setproctitle
if __name__ == "__main__":
""
setproctitle.setproctitle('python3 - proc3')
pid = os.getpid()
ppid = os.getppid()
print(f"{__file__} - Process 3 is running")
print(f"{__file__} - pid : {pid} - ppid : {ppid}")
time.sleep(10)
print(f"{__file__} : Finished process 3 : {pid}")
sys.exit(0)
当我运行 python3 main.py 时,我得到如下显示:
main.py - Run proc 1
main.py - Run proc 2
main.py - pid_id : 5696 - ppid_id : 4763
main.py : parent : psutil.Process(pid=5696, name='python3 - main', status='running', started='14:26:46')
main.py - I am waiting 6 sec.
proc1.py - Process 1 is running
proc1.py - pid : 5697 - ppid : 5696
proc2.py - Process 2 is running
proc2.py - pid : 5698 - ppid : 5696
proc2.py - Run proc 3
proc3.py - Process 3 is running
proc3.py - pid : 5699 - ppid : 5698
proc1.py : Finished process 1 : 5697
main.py - psutil.Process(pid=5697, name='python3 - proc1', status='zombie', started='14:26:46') = zombie
main.py - psutil.Process(pid=5698, name='python3 - proc2', status='sleeping', started='14:26:46') = sleeping
main.py - psutil.Process(pid=5699, name='python3 - proc3', status='sleeping', started='14:26:46') = sleeping
proc3.py : Finished process 3 : 5699
main.py - psutil.Process(pid=5697, name='python3 - proc1', status='zombie', started='14:26:46') = zombie
main.py - psutil.Process(pid=5698, name='python3 - proc2', status='sleeping', started='14:26:46') = sleeping
main.py - psutil.Process(pid=5699, name='python3 - proc3', status='zombie', started='14:26:46') = zombie
main.py - psutil.Process(pid=5697, name='python3 - proc1', status='zombie', started='14:26:46') = zombie
main.py - psutil.Process(pid=5698, name='python3 - proc2', status='sleeping', started='14:26:46') = sleeping
main.py - psutil.Process(pid=5699, name='python3 - proc3', status='zombie', started='14:26:46') = zombie
main.py - psutil.Process(pid=5697, name='python3 - proc1', status='zombie', started='14:26:46') = zombie
main.py - psutil.Process(pid=5698, name='python3 - proc2', status='sleeping', started='14:26:46') = sleeping
main.py - psutil.Process(pid=5699, name='python3 - proc3', status='zombie', started='14:26:46') = zombie
proc2.py : Finished process 2 : 5698
main.py - psutil.Process(pid=5697, name='python3 - proc1', status='zombie', started='14:26:46') = zombie
main.py - psutil.Process(pid=5698, name='python3 - proc2', status='zombie', started='14:26:46') = zombie
如您所见,proc3 首先是僵尸但是当他的父进程完成时,proc 3 消失。 但我仍然有 proc1 和 proc2 作为僵尸。
如何调用child的子进程并避免它们在完成后属于僵尸? 我读到了有关 call、popen 和 preexec_fn 的信息,并且我应该 del subprocess.popen 对象,但我不知道哪一个是正确的。
你能告诉我我该怎么办吗?
编辑:
while True:
if some_condition:
p = subprocess.Popen()
# what to do to avoid a zombie childs
for proc in processes_list:
if proc.poll() == 0:
print(f'--> I am terminate {proc} --> {proc.pid}')
proc.terminate()
processes_list.remove(proc)
I am searching a good solution for avoiding a ZOMBIE child processes when parent is still working. For example parent is working in loop and is checking some conditions. If conditions are acomplished, parent process run subprocess.
Now I wrote simple python scripts:
File main.py:
#!/usr/bin/env python3
# coding=utf-8
import os
import psutil
import subprocess
import time
import signal
import setproctitle
def main():
python_venv = 'python3'
print(f"{__file__} - Run proc 1")
a1 = [python_venv, 'proc1.py']
string_do_wywolania_part2 = ['arg1' , 'arg2']
a2 = a1 + string_do_wywolania_part2
p = subprocess.Popen(a2, preexec_fn=os.setpgrp)
print(f"{__file__} - Run proc 2")
a1 = [python_venv, 'proc2.py']
string_do_wywolania_part2 = ['arg1' , 'arg2']
a2 = a1 + string_do_wywolania_part2
p = subprocess.Popen(a2, preexec_fn=os.setpgrp)
pid_id = os.getpid()
ppid_id = os.getppid()
print(f"{__file__} - pid_id : {pid_id} - ppid_id : {ppid_id}")
parent = psutil.Process(pid_id)
print(f"{__file__} : parent : {parent}")
t = 6
print(f"{__file__} - I am waiting {t} sec.")
time.sleep(t)
if __name__ == "__main__":
"call sub processes"
setproctitle.setproctitle('python3 - main')
main()
while True:
k = 1
pid_id = os.getpid()
parent = psutil.Process(pid_id)
print()
for child in parent.children(recursive=True): # or parent.children() for recursive=False
print(f'{__file__} - {child} = {child.status()}')
k +=1
time.sleep(5)
print(f'{__file__} : Finished main')
File proc1.py
#!/usr/bin/env python3
# coding=utf-8
import os
import sys
import time
import setproctitle
if __name__ == "__main__":
setproctitle.setproctitle('python3 - proc1')
pid = os.getpid()
ppid = os.getppid()
print(f"{__file__} - Process 1 is running")
print(f"{__file__} - pid : {pid} - ppid : {ppid}")
time.sleep(5)
print(f"{__file__} : Finished process 1 : {pid}")
sys.exit(0)
proc2.file:
#!/usr/bin/env python3
# coding=utf-8
import os
import sys
import time
import subprocess
import signal
import setproctitle
if __name__ == "__main__":
setproctitle.setproctitle('python3 - proc2')
print(f"{__file__} - Process 2 is running")
try:
pid = os.getpid()
ppid = os.getppid()
print(f"{__file__} - pid : {pid} - ppid : {ppid}")
print(f"{__file__} - Run proc 3")
python_venv = 'python3'
a1 = [python_venv, 'proc3.py']
string_do_wywolania_part2 = ['arg1' , 'arg2']
a2 = a1 + string_do_wywolania_part2
p = subprocess.Popen(a2, preexec_fn=os.setpgrp)
time.sleep(15)
except Exception as e:
print(e)
time.sleep(7)
print(f"{__file__} : Finished process 2 : {pid}")
sys.exit(0)
and the last one proc3.py
#!/usr/bin/env python3
# coding=utf-8
import os
import sys
import time
import setproctitle
if __name__ == "__main__":
""
setproctitle.setproctitle('python3 - proc3')
pid = os.getpid()
ppid = os.getppid()
print(f"{__file__} - Process 3 is running")
print(f"{__file__} - pid : {pid} - ppid : {ppid}")
time.sleep(10)
print(f"{__file__} : Finished process 3 : {pid}")
sys.exit(0)
When I am running python3 main.py i am getting displays like bellow:
main.py - Run proc 1
main.py - Run proc 2
main.py - pid_id : 5696 - ppid_id : 4763
main.py : parent : psutil.Process(pid=5696, name='python3 - main', status='running', started='14:26:46')
main.py - I am waiting 6 sec.
proc1.py - Process 1 is running
proc1.py - pid : 5697 - ppid : 5696
proc2.py - Process 2 is running
proc2.py - pid : 5698 - ppid : 5696
proc2.py - Run proc 3
proc3.py - Process 3 is running
proc3.py - pid : 5699 - ppid : 5698
proc1.py : Finished process 1 : 5697
main.py - psutil.Process(pid=5697, name='python3 - proc1', status='zombie', started='14:26:46') = zombie
main.py - psutil.Process(pid=5698, name='python3 - proc2', status='sleeping', started='14:26:46') = sleeping
main.py - psutil.Process(pid=5699, name='python3 - proc3', status='sleeping', started='14:26:46') = sleeping
proc3.py : Finished process 3 : 5699
main.py - psutil.Process(pid=5697, name='python3 - proc1', status='zombie', started='14:26:46') = zombie
main.py - psutil.Process(pid=5698, name='python3 - proc2', status='sleeping', started='14:26:46') = sleeping
main.py - psutil.Process(pid=5699, name='python3 - proc3', status='zombie', started='14:26:46') = zombie
main.py - psutil.Process(pid=5697, name='python3 - proc1', status='zombie', started='14:26:46') = zombie
main.py - psutil.Process(pid=5698, name='python3 - proc2', status='sleeping', started='14:26:46') = sleeping
main.py - psutil.Process(pid=5699, name='python3 - proc3', status='zombie', started='14:26:46') = zombie
main.py - psutil.Process(pid=5697, name='python3 - proc1', status='zombie', started='14:26:46') = zombie
main.py - psutil.Process(pid=5698, name='python3 - proc2', status='sleeping', started='14:26:46') = sleeping
main.py - psutil.Process(pid=5699, name='python3 - proc3', status='zombie', started='14:26:46') = zombie
proc2.py : Finished process 2 : 5698
main.py - psutil.Process(pid=5697, name='python3 - proc1', status='zombie', started='14:26:46') = zombie
main.py - psutil.Process(pid=5698, name='python3 - proc2', status='zombie', started='14:26:46') = zombie
As you see, proc3 first is zombie but when parent process for him was finished, proc 3 disappear.
But still I have proc1 and proc2 as zombies.
How to call child's sub processes and avoid them to belong to zombie after finish?
I read info about call, popen and preexec_fn and that I should del subprocess.popen object, but I do not know which is right one.
Can you tell me what should I do?
EDITED:
while True:
if some_condition:
p = subprocess.Popen()
# what to do to avoid a zombie childs
for proc in processes_list:
if proc.poll() == 0:
print(f'--> I am terminate {proc} --> {proc.pid}')
proc.terminate()
processes_list.remove(proc)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
总结一下:
父进程必须等待子进程的退出状态。如果父进程在等待其子进程之前退出,那么最终会出现僵尸进程。
您已经考虑过拥有一个名为
processes_list< 的 Popen 对象列表/code>
您可以将
Popen.wait
与超时一起使用,例如:如果您在编辑的代码中使用
Popen.poll
,那么您应该检查None
code> 这意味着孩子是尚未完成,所以不要将其从列表中删除。您在检查0
但如果返回代码是其他内容怎么办?最后,在 proc2 文件上同样适用,您必须等待子进程完成,然后让父进程本身退出。这可以通过 Popen.wait 来实现:
To sum up:
A parent process must wait on the exit status of the child. If the parent exits before waiting on it's children then you end up with zombie processes.
You have already considered having a list of Popen objects called
processes_list
You can use
Popen.wait
with a timeout like:If you use
Popen.poll
as in your edited code then you should check forNone
which means that the child is not finished yet, so don't remove it from the list. You where checking for0
but what if the return code is something else?Finally on the
proc2
file the same applies you must wait for the child process to finish and then let the parent itself exit. This can be achived withPopen.wait
: