Spec-Zone.ru › Flask 3.0

Использование 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 и используя адаптер 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

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

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

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

© 2010 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/3.0.x/async-await/

Spec-Zone.ru

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