Spec-Zone.ru › Flask 2.3

Использование async и await

Журнал изменений

Новое в версии 2.0.

Маршруты, обработчики ошибок, функции перед запросом, после запроса и завершения могут быть функциями-генераторами, если Flask установлен с дополнительным пакетом async (pip install flask[async]). Это позволяет определять представления с async def и использовать await.

@app.route("/get-data")
async def get_data():
    data = await async_db_query(...)
    return jsonify(data)

Подключаемые представления на основе классов также поддерживают обработчики, реализованные как генераторы. Это относится к методу dispatch_request() в представлениях, унаследованных от класса flask.views.View, а также ко всем обработчикам методов HTTP в представлениях, унаследованных от класса flask.views.MethodView.

Использование async в Windows на Python 3.8

В Python 3.8 существует ошибка, связанная с asyncio в Windows. Если вы столкнетесь с чем-то вроде ValueError: set_wakeup_fd only works in main thread, обновитесь до Python 3.9.

Использование async с greenlet

При использовании gevent или eventlet для запуска приложения или модификации среды исполнения требуется greenlet>=1.0. При использовании PyPy требуется PyPy>=7.3.7.

Производительность

Функции async требуют наличия цикла событий для выполнения. Flask, как WSGI-приложение, использует одного работника для обработки одного цикла запрос/ответ. Когда запрос поступает в представление async, Flask запускает цикл событий в потоке, выполняет функцию представления в нём, а затем возвращает результат.

Каждый запрос по-прежнему использует одного работника, даже для async-представлений. Преимущество заключается в том, что вы можете запускать асинхронный код внутри представления, например, для выполнения нескольких одновременных запросов к базе данных, HTTP-запросов к внешнему API и т. д. Однако количество запросов, которые может обработать ваше приложение одновременно, останется прежним.

Асинхронный код не обязательно быстрее синхронного. Асинхронный код выгоден при выполнении одновременных задач, связанных с вводом-выводом, но, вероятно, не улучшит задачи, связанные с вычислениями. Традиционные представления Flask по-прежнему будут актуальны для большинства случаев использования, но поддержка асинхронного кода в Flask позволяет писать и использовать код, который ранее не был возможен напрямую.

Фоновые задачи

Асинхронные функции выполняются в цикле событий до завершения, после чего цикл событий останавливается. Это означает, что любые дополнительные запущенные задачи, которые не завершены к моменту завершения асинхронной функции, будут отменены. Следовательно, вы не можете запускать фоновые задачи, например, с помощью asyncio.create_task.

Если вы хотите использовать фоновые задачи, лучше использовать очередь задач для запуска фоновой работы, а не запускать задачи внутри функции представления. С этой целью вы можете запускать задачи asyncio, если Flask запускается с сервером ASGI и используется адаптер WsgiToAsgi из asgiref, как описано в ASGI. Это работает, потому что адаптер создаёт цикл событий, который постоянно работает.

Когда использовать Quart вместо Flask

Поддержка асинхронного кода в Flask менее эффективна, чем в фреймворках, ориентированных на асинхронный код, из-за того, как она реализована. Если у вас преимущественно асинхронная кодовая база, стоит рассмотреть Quart. Quart — это повторная реализация Flask, основанная на стандарте ASGI вместо WSGI. Это позволяет ему обрабатывать множество одновременных запросов, длительные запросы и веб-сокеты без необходимости в нескольких процессах или потоках.

Также уже было возможно запускать Flask с Gevent или Eventlet, чтобы получить многие преимущества асинхронной обработки запросов. Эти библиотеки модифицируют низкоуровневые функции Python для этого, в то время как async/ await и ASGI используют стандартные современные возможности Python. Решение о том, использовать Flask, Quart или что-то ещё, в конечном итоге зависит от понимания конкретных потребностей вашего проекта.

Расширения

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

Авторы расширений могут поддерживать асинхронные функции, используя метод flask.Flask.ensure_sync(). Например, если расширение предоставляет декоратор функции представления, добавьте ensure_sync перед вызовом декорированной функции.

def extension(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        ...  # Extension logic
        return current_app.ensure_sync(func)(*args, **kwargs)

    return wrapper

Проверьте журнал изменений расширения, которое вы хотите использовать, чтобы увидеть, реализована ли в нём поддержка асинхронного кода, или отправьте запрос на добавление функции или PR.

Другие циклы событий

В данный момент Flask поддерживает только asyncio. Возможно переопределить flask.Flask.ensure_sync() для изменения того, как асинхронные функции оборачиваются, чтобы использовать другую библиотеку.

© 2007–2022 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/2.3.x/async-await/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API