【发布时间】:2020-11-28 23:44:47
【问题描述】:
我无法让消费者和生产者同时运行,似乎 worker() 或 aiohttp 服务器正在阻塞 - 即使与 asyncio.gather() 同时执行
如果我改为使用 loop.create_task(worker),这将阻塞并且永远不会启动服务器。
我已经尝试了我能想象到的所有变体,包括 nest_asyncio 模块 - 我只能让这两个组件中的一个运行。
我做错了什么?
async def worker():
batch_size = 30
print("running worker")
while True:
if queue.qsize() > 0:
future_map = {}
size = min(queue.qsize(), batch_size)
batch = []
for _ in range(size):
item = await queue.get()
print("Item: "+str(item))
future_map[item["fname"]] = item["future"]
batch.append(item)
print("processing", batch)
results = await process_files(batch)
for dic in results:
for key, value in dic.items():
print(str(key)+":"+str(value))
future_map[key].set_result(value)
# mark the tasks done
for _ in batch:
queue.task_done()
def start_worker():
loop.create_task(worker())
def create_app():
app = web.Application()
routes = web.RouteTableDef()
@routes.post("/decode")
async def handle_post(request):
return await decode(request)
app.add_routes(routes)
app.on_startup.append(start_worker())
return app
if __name__ == '__main__':
loop = asyncio.get_event_loop()
queue = asyncio.Queue()
app = create_app()
web.run_app(app)
上面打印“running worker”,并没有启动AIOHTTP服务器。
def run(loop, app, port=8001):
handler = app.make_handler()
f = loop.create_server(handler, '0.0.0.0', port)
srv = loop.run_until_complete(f)
print('serving on', srv.sockets[0].getsockname())
try:
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
loop.run_until_complete(handler.finish_connections(1.0))
srv.close()
loop.run_until_complete(srv.wait_closed())
loop.run_until_complete(app.finish())
loop.close()
def main(app):
asyncio.gather(run(loop, app), worker())
if __name__ == '__main__':
loop = asyncio.get_event_loop()
queue = asyncio.Queue()
app = create_app()
main(app)
上面启动服务器,但不启动worker。
【问题讨论】:
-
看起来
worker仅在队列不为空时才等待某些内容。它将阻止其他任何东西运行,包括将东西推入队列的任何东西。当队列为空时添加类似await asyncio.sleep(0)的内容可能会有所帮助。 (相应地调整睡眠时间。) -
好像可以了,谢谢!
标签: python python-asyncio coroutine aiohttp event-loop