【发布时间】:2017-06-30 19:37:26
【问题描述】:
我有以下场景:多个工作进程将有关其当前状态的事件发送到事件调度程序。如果我们在主进程中,则该事件调度器需要处理所有事件,或者如果我们在工作进程中,则向主进程的事件调度器发出信号以处理这些事件。
这里的主要症结是事件处理也必须在主进程的主线程中,所以我不能只在线程内运行一个while True循环并等待来自worker的消息在那里处理。
所以我拥有的是这样的:
import asyncio
from concurrent.futures import ThreadPoolExecutor
from multiprocessing import current_process, Process, Queue
from threading import current_thread
from time import sleep
def get_q(q):
print("Waiting for the queue ({} / {})\n".format(current_thread().name, current_process().name))
return q.get()
async def message_q(q):
while True:
f = loop.run_in_executor(None, get_q, q)
await f
if f.result() is None:
print("Done")
return;
print("Got the result ({} / {})".format(current_thread().name, current_process().name))
print("Result is: {}\n".format(f.result()))
async def something_else():
while True:
print("Something else\n")
await asyncio.sleep(2)
def other_process(q):
for i in range(5):
print("Putting something in the queue ({})".format(current_process().name))
q.put(i)
sleep(1)
q.put(None)
q = Queue()
Process(target=other_process, args=(q,), daemon=True).start()
loop = asyncio.get_event_loop()
loop.set_default_executor(ThreadPoolExecutor(max_workers=1))
asyncio.ensure_future(message_q(q))
asyncio.ensure_future(something_else())
loop.run_until_complete(asyncio.sleep(6))
other_process() 是一个示例性的工作进程,它使用队列向主进程发出信号,主进程运行事件循环来处理内容并等待队列上的任何数据。在实际情况下,该进程会向事件调度器发出信号,该事件调度器随后将处理队列消息,将消息传递给主进程事件调度器,但这里我将其简化了一点。
但是,我对此不太满意。一次又一次地将get_q() 提交给ThreadPoolExecutor 会产生更多的开销,并且不像一个长时间运行的线程那么干净。 await f 也不是最优的,一旦队列中没有更多数据就会阻塞,这会阻止事件循环退出。我的解决方法是在工作人员完成后发送None,如果None 在队列中,则退出message_q()。
有没有更好的方法来实现这个?性能非常重要,我想将 Queue 对象保留在事件调度程序的本地,而不是将其传递给管理工作进程的代码(或需要调用某种finalize() 方法)。
【问题讨论】:
标签: python python-multiprocessing python-asyncio