проверить новую команду управления во время сна в asyncio

1

Я ищу pythonic asyncio "pattern" для конструкции, которая довольно часто появляется в моих программах.

Рабочее задание выполняет некоторые операции, обычно состоящие из нескольких шагов. Детали этих операций контролируются командами, отправленными из управляющей функции в рабочую задачу. Между отдельными шагами есть сон, и рабочий может принимать новые команды только во время этих сна. Новая команда должна немедленно освободить рабочую задачу из сна.

Команды представляют желаемое целевое состояние. Я использую очередь для связи. Однако может быть только одна цель, поэтому команды не создают настоящую очередь, но последняя заменяет все предыдущие. В очереди есть не более одного элемента.

В настоящее время я использую другую асинхронную библиотеку. Я хочу перейти на стандартный asyncio. Пример:

# warning: not asyncio code; not real code
cmd_queue = Queue()

async def worker():
    cmd = 'INIT'
    while cmd != 'STOP':
        ... do_something1 sync or async ...
        newcmd = await cmd_queue.get(timeout=SLEEPTIME1, timeout_value=None)
        if newcmd is not None:
            cmd = newcmd
            continue
        ... do_something2 sync or async ...
        newcmd = await cmd_queue.get(timeout=SLEEPTIME2, timeout_value=None)
        if newcmd is not None:
            cmd = newcmd
            continue

def controlloler():
    ...
    if newcmd:
        cmd_queue.clear() # replaces a waiting command
        cmd_queue.put(newcmd) # put_nowait() in asyncio
    ...

Я мог бы переписать эту форму queue.get на асинхронный код:

try:
    cmd=wait_for(cmd_queue.get(), timeout=SLEEPTIME)
    continue # or process otherwise
except asyncio.TimeoutError:
    pass

но я думаю, может быть, есть более простое решение. OTOH Если у вас есть асинхронный опыт и думаю, что очередь с тайм-аутом - это путь, который мне тоже поможет.

Я попытался выполнить поиск, но не смог найти подходящие ключевые слова для моей проблемы (то же самое относится к заголовку вопроса).

Теги:
python-asyncio

1 ответ

1
Лучший ответ

Конечно, нет ничего плохого в вашей реализации тайм-аута. Методы для примитивов синхронизации asyncio намеренно не поддерживают явные аргументы тайм-аута, оставляя его вызывающему пользователю использовать отмену или wait_for для тайм-аута, когда это необходимо.

Что касается одноэлементной очереди, я бы рассмотрел ее замену на Future, которое предназначено не только для хранения одного значения, но также очень легкое в asyncio, учитывая, что это основная абстракция, используемая для создания почти всего остального.

Вместо wait_for(cmd_queue.get(),...) вы должны написать wait_for(cmd_future,...), а вместо cmd_queue.put(value) вы должны написать cmd_future.set_result(value). Единственное важное отличие состоит в том, что будущее одноразовое, поэтому после получения элемента вам нужно назначить новое будущее для cmd_future.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню