#python #task #python-asyncio
Вопрос:
Я использую задачи для обработки предварительно загруженной очереди, поэтому в очередь помещаются все ее элементы до создания задач. Является ли лучшей формой сделать некоторое время верно в моей задаче, а затем присоединиться к очереди, чтобы дождаться, пока она опустеет в моей сопрограмме, а затем, наконец, отменить задачи, или было бы так же эффективно и, возможно, проще (IMHO) создать задачи, а затем просто дождаться каждой из них? Затем код задачи выполнит queue.get_nowait()
операцию vs, выполнив await queue.get()
попытку/исключение, и как только я поймаю пустую очередь, моя задача будет выполнена.
Так что прямо сейчас, и большая часть того, что я читаю, делает это:
while True:
item = await queue.get()
<do some stuff>
queue.task_done()
а затем в вызывающем:
tasks = [asyncio.create_task(worker()) for x in <some iterable>]
await queue.join()
for task in tasks:
task.cancel()
asyncio.gather(...)
Это имеет смысл в тех случаях, когда производители могут помещать элементы в очередь одновременно с выполнением задач. Но я этого не делаю. Я помещаю их всех в очередь перед выполнением задач, и очередь никогда не увеличится в длину, как только это будет сделано. Поэтому я думаю вот о чем:
more = True
while more:
try:
item = queue.get_nowait()
<do some stuff>
queue.task_done()
except asyncio.QueueEmpty:
more=False
а затем в вызывающем
<populate the queue>
tasks = [asyncio.create_task(worker()) for x in <some iterable>]
for task in tasks:
await task
await asyncio.gather(...)
Я закодировал это, и, похоже, оно работает просто отлично и, похоже, предотвращает кучу исключений отмены и фьючерсов, которые не используются, типа мусора. Есть ли какая-то причина держаться подальше от этой идеи, когда у меня может быть эта заполненная очередь и нет запущенных «производителей»? Если это приемлемо, нужно ли вообще вызывать этот сбор? В этот момент я знаю, что задачи выполнены, они фактически полностью завершены, они не застряли в цикле, и я не жду, когда они будут отменены.
Спасибо.
Комментарии:
1. Вы уже заглядывали в модуль concurrent.futures? В нем есть исполнители пула потоков/процессов, которые, я полагаю, могли бы упростить это docs.python.org/3/library/…