Spec-Zone.ru › Flask 2.1

Использование 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.

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

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

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

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

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

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

Если вы хотите использовать фоновые задачи, лучше использовать очередь задач для запуска фоновой работы, а не запускать задачи в функции представления. С этой целью вы можете запускать задачи asyncio, предоставляя Flask сервером ASGI и используя адаптер asgiref WsgiToAsgi, как описано в 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.1.x/async-await/

Spec-Zone.ru

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