Python 3.6.6
这是代码:
import asyncio
import time
from concurrent.futures import ProcessPoolExecutor
executor_processes = ProcessPoolExecutor(2)
def calculate():
while True:
print("while")
time.sleep(1)
async def async_method():
loop_ = asyncio.get_event_loop()
loop_.run_in_executor(executor_processes, calculate)
await asyncio.sleep(1)
print("finish sleep")
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(async_method())
print("main_thread is finished")
输出:
同时
完成睡眠
main_thread完成
而
而
...
我希望子进程将被终止,就像使用守护程序属性生成进程时一样:
import asyncio
import time
import multiprocessing
def calculate():
while True:
print("while")
time.sleep(1)
async def async_method():
proc = multiprocessing.Process(target=calculate)
proc.daemon = True
proc.start()
await asyncio.sleep(1)
print("finish sleep")
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(async_method())
print("main_thread is finished")
输出:
同时
完成睡眠
main_thread完成
问题:如何将loop_.run_in_executor(executor_processes, calculate)
的行为更改为“类似守护程序”的行为?
答案 0 :(得分:1)
您显示的代码显然只是一个小例子,以演示您希望实现的目标。我们不知道您的实际任务/问题。但老实说,我不相信您在这里的正确路径。
ProcessPoolExecutor
是concurrent.futures
标准库软件包的一部分。他们在调用submit()
后将Future
返回给呼叫者。 Future
是尚未完成的计算结果的代理。这是一个承诺;尽管该术语在此情况下在技术上不太正确。有关区别,请参见Wiki page。
这暗示着计算是 expected 在有限的时间内完成并产生结果。
这就是为什么Python中的ThreadPoolExecutor
和ProcessPoolExecutor
实现不允许您生成守护进程。要求承诺一个您实际上不希望实现的结果没有多大意义。
但是,可以直接回答问题的选项:
1-子类ProcessPoolExecutor
:
您可以拦截_adjust_process_count()
中p.daemon = True
中新进程的创建和启动。但是,由于concurrent.futures
在设计时并未考虑无限期运行的任务,因此不会有太大帮助。与multiprocessing
不同,concurrent.futures.process
定义了一个甚至不考虑守护进程的exit handler。它只是尝试join()
进行所有操作,而无限循环可能会花费一些时间。
2-定义自己的退出处理程序:
您可以做multiprocessing
和concurrent.futures.process
都做的事情:定义退出处理程序,该处理程序在您的python进程即将关闭。 atexit可以帮助您:
import atexit
executor_processes = ProcessPoolExecutor(2)
def calculate():
while True:
print("while")
time.sleep(1)
def end_processes():
[proc.terminate() for proc in multiprocessing.active_children()]
async def async_method():
[...]
if __name__ == '__main__':
atexit.register(end_processes)
loop = asyncio.get_event_loop()
[...]
注意:这将终止所有活动的子进程,直到该进程结束为止。如果有子进程想要正常关闭,请保留一个句柄并在代码末尾执行该操作。
另外请注意,进程可以拒绝遵守terminate()
。 kill()
是您的最后度假胜地。