Должен ли я использовать task.cancel() и бесконечные циклы для задач asyncio с фиксированным размером очереди

#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/…