Топ-5 асинхронних веб-фреймворків для Python

Асинхронне програмування набуло значного поширення в Python. Якщо ви займаєтеся веб-розробкою, у вашому розпорядженні є безліч чудових фреймворків на вибір!

На сьогоднішній день, асинхронність перестала бути просто модним трендом у Python-спільноті. Завдяки впровадженню бібліотеки asyncio у версії 3.5, Python визнав вплив Node.js на веб-розробку. Це призвело до появи двох нових ключових слів у мові – async та await. Це був важливий крок, оскільки Python відомий своєю обережністю щодо розширення основного синтаксису, що підкреслює фундаментальну важливість асинхронних можливостей для розробників.

Внаслідок цього, для асинхронного програмування відкрилися нові можливості. Як нові, так і старі бібліотеки почали використовувати співпрограми, популярність асинхронних фреймворків зросла, і нові продовжують з’являтися. Продуктивність, що не поступається Node.js, або навіть перевищує її, стала реальністю. Якщо ваші робочі навантаження не пов’язані зі значними обчисленнями на ЦП, ви можете обробляти кілька тисяч запитів на секунду.

Але досить мотиваційних розмов!

Давайте розглянемо сучасний стан асинхронних фреймворків Python і ознайомимося з деякими з найкращих.

Tornado

Цікаво, що Tornado – це зовсім не новий фреймворк. Його перший реліз відбувся у 2009 році (десять років тому на момент написання), і відтоді він фокусується на наданні надійних можливостей асинхронного програмування з високим рівнем паралелізму.

Tornado, по суті, не є виключно веб-фреймворком. Це набір асинхронних модулів, які також використовуються для побудови веб-платформи. Зокрема, ці модулі включають:

  • Співпрограми та інші примітиви (tornado.gen, tornado.locks, tornado.queues тощо)
  • Мережеві модулі (tornado.ioloop, tornado.iostream тощо)
  • Асинхронні сервери та клієнти (tornado.httpserver, tornado.httpclient тощо)

Вони були об’єднані для створення модулів фреймворку: tornado.web, tornado.routing, tornado.template тощо.

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

def make_app():
    return tornado.web.Application([
        (r"/", MainHandler),
    ])

if __name__ == "__main__":
    app = make_app()
    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()

Tornado має відданих прихильників у спільноті Python і використовується досвідченими архітекторами для створення високопродуктивних систем. Це фреймворк, який давно вирішує проблеми паралелізму, але, можливо, не став мейнстримом, оскільки він не підтримує стандарт WSGI і був занадто “великим” (не забувайте, що більшість Python-бібліотек є синхронними).

Sanic

Sanic є “сучасним” фреймворком у прямому значенні цього слова. Він не підтримує версії Python нижче 3.6, має прозорий синтаксис async/await “з коробки” і не змушує вас вивчати багато документації, щоб написати ваш перший HTTP-обробник.

В результаті синтаксис є досить простим. Він нагадує код, який ви б писали з будь-яким іншим мікрофреймворком (таким як Flask, CherryPy), з додаванням кількох асинхронних елементів:

from sanic import Sanic
from sanic.response import json

app = Sanic()

@app.route("/")
async def test(request):
    return json({"hello": "world"})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

Sanic є одним з найпопулярніших і улюблених асинхронних фреймворків в екосистемі Python. Він надає майже всі необхідні функції для ваших проєктів – маршрутизація, проміжне ПЗ, файли cookie, управління версіями, blueprint, представлення на основі класів, статичні файли, потокова передача, сокети тощо. А те, чого він не пропонує “з коробки” – шаблони, підтримка баз даних, файловий ввід-вивід, черги – можна додати, оскільки для них є достатньо асинхронних бібліотек.

Vibora

Vibora є близьким аналогом Sanic, але з акцентом на те, щоб стати найшвидшим веб-сервером Python. При відвідуванні їхнього веб-сайту одразу бачимо порівняльну таблицю продуктивності:

Як ви бачите, Vibora стверджує, що він в декілька разів швидший за класичні фреймворки і більш ніж вдвічі швидший за свого найближчого конкурента, Sanic. Звичайно, до таких бенчмарків слід ставитися з обережністю. 🙂

Хоча за синтаксисом і функціональністю Vibora схожа на Sanic (можливо, навіть трохи краща, оскільки об’єднує популярні бібліотеки та надає шаблони “з коробки”), Sanic є більш зрілим, оскільки він існує довше і має більшу спільноту.

from vibora import Vibora, JsonResponse

app = Vibora()

@app.route('/')
async def home():
    return JsonResponse({'hello': 'world'})

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=8000)

Однак, якщо ви цінуєте продуктивність, Vibora може бути вашим вибором. На момент написання статті Vibora повністю переписується, щоб стати ще швидшою, а посилання на її продуктивну версію вказує, що вона знаходиться в стадії “інтенсивної розробки”. Це може розчарувати тих, хто обрав Vibora раніше, оскільки їм, можливо, доведеться зіткнутися зі значними змінами, але варто пам’ятати, що у світі асинхронізації Python ще тільки початок, і ніхто не очікує стабільності.

Quart

Якщо вам подобається розробка у Flask, але вас турбує відсутність асинхронної підтримки, вам сподобається Quart.

Quart відповідає стандарту ASGI, який є наступником відомого стандарту WSGI і пропонує асинхронну підтримку. Цікавою особливістю Quart є не тільки його схожість на Flask, але й фактична сумісність з Flask API! Автор цього фреймворку хотів зберегти відчуття Flask і просто додати до нього підтримку async, WebSockets і HTTP 2. Як наслідок, ви можете вивчати Quart, використовуючи документацію Flask, пам’ятаючи лише, що функції в Quart є асинхронними.

from quart import Quart

app = Quart(__name__)

@app.route('/')
async def hello():
    return 'hello'

app.run()

За відчуттями це (майже) ідентично Flask, чи не так?!

Оскільки Quart є еволюцією Flask, всі його можливості доступні: маршрутизація, проміжне ПЗ, сесії, шаблони, blueprints тощо. Фактично, ви навіть можете використовувати розширення Flask безпосередньо в Quart. Єдиним обмеженням є підтримка Python 3.7+, але якщо ви не використовуєте найновішу версію Python, можливо, async – це не найкращий вибір. 🙂

Документація необхідна, якщо у вас немає попереднього досвіду роботи з Flask, але я рекомендую Quart, оскільки це, мабуть, єдиний асинхронний фреймворк, який скоро досягне релізу 1.0.

FastAPI

Останній, але найвражаючий фреймворк у цьому списку – це FastAPI. Ні, це не фреймворк лише для API; насправді, FastAPI виглядає як фреймворк із найбагатшою функціональністю та документацією, з яким я зустрічався, вивчаючи асинхронні фреймворки Python.

Варто зазначити, що автор фреймворку ретельно вивчив декілька інших фреймворків, починаючи від таких, як Django, і закінчуючи сучасними, як Sanic, а також розглянув різні підходи в NestJS (Node.js, веб-фреймворк на TypeScript). Ви можете ознайомитися з їхньою філософією розробки та детальними порівняннями тут.

Синтаксис досить приємний; можна навіть стверджувати, що він набагато кращий за інші фреймворки, які ми розглядали:

from fastapi import FastAPI

app = FastAPI()

@app.get("/users/me")
async def read_user_me():
    return {"user_id": "the current user"}

@app.get("/users/{user_id}")
async def read_user(user_id: str):
    return {"user_id": user_id}

А тепер перелік чудових функцій, які роблять FastAPI кращим за інші фреймворки:

Автоматична генерація документації API: після написання ваших кінцевих точок, ви можете працювати з API за допомогою зручного інтерфейсу користувача. Підтримуються SwaggerUI, ReDoc та інші.

Фреймворк також виконує автоматичне документування моделей даних з використанням JSON schema.

Сучасна розробка: так, слово “сучасний” часто використовується, але я вважаю, що FastAPI дійсно це підтверджує. Впровадження залежностей і підказка типів є важливими елементами, які забезпечують не лише хороші принципи кодування, але й запобігають помилкам у довгостроковій перспективі.

Розширена документація: не знаю як ви, але я ціную хорошу документацію. І в цій області FastAPI беззаперечно виграє. Він має багато сторінок документації, де пояснюється майже кожна деталь. Я відчуваю, що в цю документацію вкладено душу і серце, і єдиним порівнянням, яке я можу знайти, є документація Django (так, документація FastAPI настільки хороша!).

Додаткові можливості: FastAPI підтримує WebSockets, Streaming, а також GraphQL, на додаток до традиційних функцій, таких як CORS, сесії, cookies тощо.

А як щодо продуктивності? FastAPI побудовано на базі чудової бібліотеки Starlette, що робить його продуктивність співмірною з Node, а в деяких випадках навіть з Go! В цілому, я відчуваю, що FastAPI буде лідирувати серед асинхронних фреймворків Python.

Висновок

Сьогодні у світі асинхронного Python відбувається багато змін. З’являються нові фреймворки, старі переписуються, а бібліотеки адаптуються до асинхронної поведінки. Хоча Python має вбудовану підтримку циклу подій, і ви можете зробити асинхронними окремі частини вашого застосунку, ви можете обрати готовий фреймворк. Пам’ятайте про довгострокову перспективу: деякі асинхронні фреймворки Python знаходяться на ранніх стадіях розвитку, що може ускладнити процес розробки. Тому обережність – це важливо!

Але, загалом, Python готовий до того, щоб забезпечити високу продуктивність у веб-фреймворках. Якщо ви давно думали про перехід на Node, тепер вам це не обов’язково! 🙂

Звучить цікаво? Вивчайте Python вже сьогодні!