最佳答案
让我们假设我们有一大堆链接要下载,每个链接可能需要不同的时间来下载。我被允许下载使用最大3连接只。现在,我想确保使用异步有效地完成这项工作。
下面是我试图实现的目标: 在任何时候,尽量确保我至少有3个下载运行。
Connection 1: 1---------7---9---
Connection 2: 2---4----6-----
Connection 3: 3-----5---8-----
数字表示下载链接,而连字符表示等待下载。
这是我正在使用的代码
from random import randint
import asyncio
count = 0
async def download(code, permit_download, no_concurrent, downloading_event):
global count
downloading_event.set()
wait_time = randint(1, 3)
print('downloading {} will take {} second(s)'.format(code, wait_time))
await asyncio.sleep(wait_time) # I/O, context will switch to main function
print('downloaded {}'.format(code))
count -= 1
if count < no_concurrent and not permit_download.is_set():
permit_download.set()
async def main(loop):
global count
permit_download = asyncio.Event()
permit_download.set()
downloading_event = asyncio.Event()
no_concurrent = 3
i = 0
while i < 9:
if permit_download.is_set():
count += 1
if count >= no_concurrent:
permit_download.clear()
loop.create_task(download(i, permit_download, no_concurrent, downloading_event))
await downloading_event.wait() # To force context to switch to download function
downloading_event.clear()
i += 1
else:
await permit_download.wait()
await asyncio.sleep(9)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main(loop))
finally:
loop.close()
结果与预期一致:
downloading 0 will take 2 second(s)
downloading 1 will take 3 second(s)
downloading 2 will take 1 second(s)
downloaded 2
downloading 3 will take 2 second(s)
downloaded 0
downloading 4 will take 3 second(s)
downloaded 1
downloaded 3
downloading 5 will take 2 second(s)
downloading 6 will take 2 second(s)
downloaded 5
downloaded 6
downloaded 4
downloading 7 will take 1 second(s)
downloading 8 will take 1 second(s)
downloaded 7
downloaded 8
但我的问题是:
目前,我只需要等待9秒钟,以保持主要功能运行,直到下载完成。在退出 main
函数之前,是否有一种等待最后一次下载完成的有效方法?(我知道有 asyncio.wait
,但是我需要存储所有的任务引用来使它工作)
什么样的图书馆能完成这样的任务?我知道 javascript 有很多异步库,但 Python 呢?
编辑: 2. 什么样的库能够处理常见的异步模式? (类似于 异步)