Можно ли заставить декоратор запускать функции блокировки в asyncio executor? - PullRequest
1 голос
/ 08 марта 2019

Возможно, мне понадобится помощь, чтобы лучше сформулировать этот вопрос.Я пишу асинхронный интерфейс API, через Python3.7, и с классом (под названием Worker()).Worker имеет несколько методов блокировки, которые я хочу запустить с помощью loop.run_in_executor().

Я бы хотел создать декоратор. Я могу просто добавить над всеми не async методами в Worker, но я продолжаю сталкиваться с проблемами.

Мне говорят, что мне нужно await wraps() в декораторе ниже:

def run_method_in_executor(func, *, loop=None):
    async def wraps(*args):
        _loop = loop if loop is not None else asyncio.get_event_loop()
        return await _loop.run_in_executor(executor=None, func=func, *args)
    return wraps

, который отбрасывает назад: RuntimeWarning: coroutine 'run_method_in_executor.<locals>.wraps' was never awaited

Яне вижу, как я мог бы правильно await wraps(), так как содержащая и украшенная функции не асинхронны.Не уверен, что это связано с неправильным пониманием asyncio или с неправильным пониманием декораторов.

Любая помощь (или уточнение помощи) будет принята с благодарностью!

1 Ответ

2 голосов
/ 08 марта 2019

Not_a_Golfer ответил на мой вопрос в комментариях.

Изменение внутренней функции wraps() из сопрограммы в генератор решило проблему:

def run_method_in_executor(func, *, loop=None):
    def wraps(*args):
        _loop = loop if loop is not None else asyncio.get_event_loop()
        yield _loop.run_in_executor(executor=None, func=func, *args)
    return wraps

Edit: Это было действительно полезно для ввода-вывода, но я не понял, как await выдать функцию-исполнитель, что означает, что будет создавать условия гонки, если я полагаюсь на украшенную функцию для обновления какое-то значение, используемое любой из моих других асинхронных функций.

...