我征求你的意见。我想在一个简单的例子中理解异步的工作。根据传说,你需要创建1000个返回一些结果的工人。但是你需要在准备好后立即归还它。 这是一个例子:
import asyncio
async def worker(number):
print("worker # %d" % number)
await asyncio.sleep(0)
return str(number)
async def print_when_done(tasks):
for res in asyncio.as_completed(tasks):
print("Result worker %s" % await res)
coros = [worker(i) for i in range(10)]
loop = asyncio.get_event_loop()
loop.run_until_complete(print_when_done(coros))
loop.close()
问题是这个例子的工作结果不是同步的,它只是在不阻塞主进程的情况下调用函数,最后它返回所有函数的响应
worker # 2
worker # 3
worker # 4
worker # 1
worker # 0
Result worker 2
Result worker 3
Result worker 4
Result worker 1
Result worker 0
但如何以相似性实现结果:
worker # 2
worker # 3
worker # 4
Result worker 3
Result worker 2
worker # 1
Result worker 4
worker # 0
Result worker 1
Result worker 0
您可以创建一个ThreadPoolExecutor,或者ProcessPoolExecutor。但是,为什么你需要Asyncio,你可以创建没有它的线程并使用它们。
答案 0 :(得分:3)
您正在寻找asyncio.wait
:
stopFyon
但是为什么你需要Asyncio,你可以创建没有它的线程并使用它们。
当然,线程可以更高效,你可以用它们做更多的事情,但单线程异步协作多任务更容易协调。
答案 1 :(得分:1)
它只是调用函数而不阻塞主进程,并且在 最后它返回所有函数的响应
它同时启动所有工作程序,它应该是这样,立即计算它们的结果(因为worker不包含任何实际的I / O阻塞)并同时返回结果。
如果你想看到工人在不同的时间返回结果,你应该让他们执行不同的时间 - 例如,通过放置await asyncio.sleep(randint(1, 3))
而不是你的0睡眠。
我不确定我理解你为什么要这样:
worker # 2
worker # 3
worker # 4
Result worker 3
由于您在每个工作者的顶部都有print
(之前没有一些I / O阻止操作)并且同时运行所有工作程序 - 您会在任何结果之前立即看到所有工作人员打印。
我的随机猜测是你可能想要限制并行运行的工人数量?在这种情况下,您可以使用asyncio.Semaphore等同步原语。
以下示例包含以上所有内容:
import asyncio
from random import randint
sem = asyncio.Semaphore(3) # don't allow more then 3 workers parallely
async def worker(number):
async with sem:
print("started # %d" % number)
await asyncio.sleep(randint(1, 3))
return str(number)
async def main():
coros = [worker(i) for i in range(10)]
for res in asyncio.as_completed(coros):
print("finished %s" % await res)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main())
finally:
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()
输出:
started # 0
started # 6
started # 7
started # 2
finished 7
started # 8
finished 0
started # 3
finished 6
started # 9
finished 2
started # 4
finished 8
started # 1
started # 5
finished 3
finished 9
finished 4
finished 1
finished 5