Как ограничить параллелизм с помощью Python asyncio?Python

Программы на Python
Ответить
Anonymous
 Как ограничить параллелизм с помощью Python asyncio?

Сообщение Anonymous »

Предположим, что у нас есть несколько ссылок для загрузки, и загрузка каждой ссылки может занять разное время. И мне разрешено скачивать, используя максимум 3 соединения. Теперь я хочу убедиться, что делаю это эффективно, используя asyncio.
Вот чего я пытаюсь достичь: в любой момент времени постарайтесь убедиться, что у меня запущено как минимум 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 секунд, чтобы основная функция работала до завершения загрузки. Есть ли эффективный способ дождаться завершения последней загрузки перед выходом из основной функции? (Я знаю, что есть asyncio.wait, но мне нужно сохранить все ссылки на задачи, чтобы он работал)
  • Какая хорошая библиотека выполняет задачи такого рода? Я знаю, что в javascript есть множество асинхронных библиотек, но как насчет Python?
Изменить:
2. Какая хорошая библиотека заботится об распространенных асинхронных шаблонах? (Что-то вроде асинхронного)
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»