Python 中控制子进程流的最佳方法是什么?
What is the best way to control the flow of the child processes in Python?
我正在尝试 运行,暂停并终止来自父进程的 Python 中的子进程。我曾尝试使用 multiprocessing.Value
,但由于某种原因,尽管我使用了 terminate
和 join
所有进程,但父进程从未完全完成。我的用例是这样的:
def child(flow_flag):
while True:
with flow_flag.get_lock():
flag_value = flow_flag.value
if flag_value == 0:
print("This is doing some work")
elif flag_value == 1:
print("This is waiting for some time to check back later")
time.sleep(5)
else:
print("Time to exit")
break
def main():
flow_flag = Value('i', 0)
processes = [Process(target=child, args=(flow_flag,)) for i in range(10)]
[p.start() for p in processes]
print("Waiting for some work")
with flow_flag.get_lock():
flow_flag.value = 1
print("Do something else")
with flow_flag.get_lock():
flow_flag.value = 0
print("Waiting for more work")
with flow_flag.get_lock():
flow_flag.value = 2
print("Exiting")
for p in processes:
p.terminate()
p.join()
这永远无法正常完成,我最终不得不 Ctrl+C
。然后我看到这条消息:
Traceback (most recent call last):
File "/home/abcde/anaconda3/lib/python3.7/threading.py", line 1308, in _shutdown
lock.acquire()
KeyboardInterrupt
有什么更好的方法?仅供参考,在等待其他事情的同时,我正在产生一些其他进程。我也让它们没有正确终止,而且我也在使用它们 Value
。当我切换到对他们使用 Queue
时,它得到了修复。但是,Queue
似乎不适合上述情况。
P.S。 : 我正在进入 Ubuntu 18.04.
编辑:经过大量调试,未退出原来是因为我正在使用的库,我不怀疑会导致此问题。我为误报道歉。感谢您就控制子进程的更好方法提出建议。
在 FreeBSD 12.1(64 位)上使用 Python 3.7.7 运行 我无法重现您的问题。
修复缩进并添加必要的导入后更改后的程序运行正常 AFAICT。
顺便说一句,您可能想要 import sys
并添加
sys.stdout.reconfigure(line_buffering=True)
到您 main()
.
的开头
你的程序对我有用,但让我插话 "is there another way"。您可以创建一个共享事件对象,而不是每隔 5 秒轮询一次,让子进程知道它们何时可以完成工作。不要轮询值 1,而是等待事件。
from multiprocessing import *
import time
import os
def child(event, times_up):
while True:
event.wait()
if times_up.value:
print(os.getpid(), "time to exit")
return
print(os.getpid(), "doing work")
time.sleep(.5)
def main():
manager = Manager()
event = manager.Event()
times_up = manager.Value(bool, False)
processes = [Process(target=child, args=(event, times_up)) for i in range(10)]
[p.start() for p in processes]
print("Let processes work")
event.set()
time.sleep(2)
print("Make them stop")
event.clear()
time.sleep(4)
print("Make them go away")
times_up.value = True
event.set()
print("Exiting")
for p in processes:
p.join()
if __name__ == "__main__":
main()
我正在尝试 运行,暂停并终止来自父进程的 Python 中的子进程。我曾尝试使用 multiprocessing.Value
,但由于某种原因,尽管我使用了 terminate
和 join
所有进程,但父进程从未完全完成。我的用例是这样的:
def child(flow_flag):
while True:
with flow_flag.get_lock():
flag_value = flow_flag.value
if flag_value == 0:
print("This is doing some work")
elif flag_value == 1:
print("This is waiting for some time to check back later")
time.sleep(5)
else:
print("Time to exit")
break
def main():
flow_flag = Value('i', 0)
processes = [Process(target=child, args=(flow_flag,)) for i in range(10)]
[p.start() for p in processes]
print("Waiting for some work")
with flow_flag.get_lock():
flow_flag.value = 1
print("Do something else")
with flow_flag.get_lock():
flow_flag.value = 0
print("Waiting for more work")
with flow_flag.get_lock():
flow_flag.value = 2
print("Exiting")
for p in processes:
p.terminate()
p.join()
这永远无法正常完成,我最终不得不 Ctrl+C
。然后我看到这条消息:
Traceback (most recent call last):
File "/home/abcde/anaconda3/lib/python3.7/threading.py", line 1308, in _shutdown
lock.acquire()
KeyboardInterrupt
有什么更好的方法?仅供参考,在等待其他事情的同时,我正在产生一些其他进程。我也让它们没有正确终止,而且我也在使用它们 Value
。当我切换到对他们使用 Queue
时,它得到了修复。但是,Queue
似乎不适合上述情况。
P.S。 : 我正在进入 Ubuntu 18.04.
编辑:经过大量调试,未退出原来是因为我正在使用的库,我不怀疑会导致此问题。我为误报道歉。感谢您就控制子进程的更好方法提出建议。
在 FreeBSD 12.1(64 位)上使用 Python 3.7.7 运行 我无法重现您的问题。
修复缩进并添加必要的导入后更改后的程序运行正常 AFAICT。
顺便说一句,您可能想要 import sys
并添加
sys.stdout.reconfigure(line_buffering=True)
到您 main()
.
你的程序对我有用,但让我插话 "is there another way"。您可以创建一个共享事件对象,而不是每隔 5 秒轮询一次,让子进程知道它们何时可以完成工作。不要轮询值 1,而是等待事件。
from multiprocessing import *
import time
import os
def child(event, times_up):
while True:
event.wait()
if times_up.value:
print(os.getpid(), "time to exit")
return
print(os.getpid(), "doing work")
time.sleep(.5)
def main():
manager = Manager()
event = manager.Event()
times_up = manager.Value(bool, False)
processes = [Process(target=child, args=(event, times_up)) for i in range(10)]
[p.start() for p in processes]
print("Let processes work")
event.set()
time.sleep(2)
print("Make them stop")
event.clear()
time.sleep(4)
print("Make them go away")
times_up.value = True
event.set()
print("Exiting")
for p in processes:
p.join()
if __name__ == "__main__":
main()