asyncio run или run_until_complete - PullRequest
       11

asyncio run или run_until_complete

1 голос
/ 09 апреля 2019

Я использую asyncio для приложения очень простым способом. Проверяя большинство учебных пособий по Интернету (и даже официальных документов), я вижу, что они используют get_event_loop() и loop.run_until_complete():

import asyncio

async def say(what, when):
    await asyncio.sleep(when)
    print(what)

loop = asyncio.get_event_loop()
loop.run_until_complete(say('hello world', 1))
loop.close()

Но в Python 3.7 документах мы можем прочитать:

Разработчики приложений, как правило, должны использовать высокоуровневые асинхронные функции, такие как asyncio.run () , и редко должны ссылаться на объект цикла или вызывать его методы. Этот раздел предназначен в основном для авторов низкоуровневого кода, библиотек и инфраструктур, которым необходим более точный контроль поведения цикла событий.

Мне показалось, что он намного чище и проще в использовании, но он работает только для Python 3.7+. Поэтому здесь я должен был бы сделать выбор: использовать ли Python 3.7+ и run() или сделать его совместимым с Python 3.6 и использовать цикл обработки событий. Как бы вы справились с этим? Есть ли простой способ сделать его обратно совместимым с Python 3.6? Должен ли я сначала проверить версию Python и использовать ее так или иначе, основываясь на этом, пока Python 3.7 не станет распространенной версией?

1 Ответ

1 голос
/ 09 апреля 2019

Есть ли простой способ сделать [код, использующий asyncio.run] обратно совместимым с Python 3.6?

Вы можете реализовать простую замену asyncio.run и вызывать ее в более старых версиях Python:

def run(aw):
    if sys.version_info >= (3, 7):
        return asyncio.run(aw)

    # Emulate asyncio.run() on older versions
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    try:
        return loop.run_until_complete(aw)
    finally:
        loop.close()
        asyncio.set_event_loop(None)

Преимущество этого подхода перед использованием loop.run_until_complete() заключается в том, что вы выполняете свой код в семантике новой asyncio.run, даже в старых версиях Python. (Например, вы всегда будете запускать только что созданный цикл обработки событий.) Отбросить поддержку для pre-3.7 Python так же просто, как удалить прокладку run и вызвать asyncio.run напрямую.

...