Иногда хочется попробовать что-то новое, но в рабочих проектах это не всегда возможно. Поэтому предлагаю всем вместе пощупать несколько относительно новых web-фреймворков и посмотреть, что это такое и с чем их едят.
Для начала придумаем проект, который не займёт много времени(надеюсь) и над которым будет интересно посидеть пару вечеров.
С чего начнем?
Сделаем простую типовую апишку, с помощью которой можно будет создавать и редактировать резюме. Ну, а тренироваться будем на кошках.

Что нам нужно:
📄 Карточка-резюме с опытом и навыками
🔗 Ссылка для просмотра
✏️ Редактирование и добавление информации
📦 База данных для хранения и поиска
Остальное пока останется за бортом. Нам это сейчас не надо.
Инструменты:
python, litestar, coverage, pytest, ruff, docker, make, granian, sqlalchemy, alembic, asyncpg, keydb, msgspec, uv, pyenv. Выглядит как какой-то набор тэгов, но всё это нам понадобиться, постепенно.
Самым интересным для многих будет посмотреть granian, keydb и на litestar и сравнить его с fastapi.
Небольшой дисклеймер: Все персонажи выдуманы, любые совпадения — случайны. Если видите ошибки в коде или в тексте, пишите в комментариях, буду рад всё поправить. Конструктивная критика, любые предложения, какая-то новая фича или что-то еще, чего бы хотелось увидеть в этом проекте — приветствуются.
Проектирование системы

"Системы состоят из подсистем, подсистемы — из подподсистем и так до бесконечности — именно поэтому мы проектируем снизу вверх." (Алан Перлис)
Настраиваем окружение
Итак, займёмся делом. Начнём с установки всего необходимого для проекта. Создадим виртуальное окружение и установим зависимости, сконфигурируем Docker и т. д. Я пользуюсь Ubuntu, так что, отталкиваться будем от этой ОС.
Устанавливаем pyenv.
Pyenv — это инструмент для управления версиями Python, который позволяет пользователям устанавливать и переключаться между несколькими версиями интерпретатора.
Под линукс pyenv рекомендуют устанавливать так:
curl -fsSL https://pyenv.run | bashДалее настраиваем свой shell для pyenv (у меня это zsh):
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init - zsh)"' >> ~/.zshrcи перезагружаем шел.
source ~/.zshrcПеред тем, как пойдём дальше, установим зависимости:
sudo apt update && sudo apt install -y build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev curl git \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev✅ Ожидаемый результат:
pyenv --versionВывод:
pyenv 2.x.xТут главное не запутаться, потому что ещё есть:
pyenv version # выводит текущую версию питона и источник
pyenv versions # выводит список версий питона доступных в pyenvПосмотреть доступные для установки версии можно так:
pyenv install -lА установить нужную — так:
pyenv install 3.13.1Устанавливаем direnv.
direnv — это менеджер переменных окружения для вашего командного интерпретатора, который автоматически загружает и выгружает переменные окружения в зависимости от текущего каталога. Это позволяет управлять проектными переменными окружения, не загромождая глобальные конфигурационные файлы, такие как ~/.profile.
Основные характеристики Direnv:
Автоматическая загрузка переменных: Direnv проверяет наличие файла .envrc в текущем и родительских каталогах перед каждой командной строкой. Если файл найден и разрешен, его содержимое загружается, а переменные становятся доступными в текущем сеансе.
Поддержка различных оболочек: Direnv интегрируется с популярными оболочками, такими как Bash, Zsh и Fish, что делает его универсальным инструментом для разных пользователей.
Локальные настройки: Вы можете определять переменные окружения для конкретных проектов, что позволяет избежать конфликтов между различными проектами и их зависимостями.
Обработка скриптов: Файл .envrc может содержать произвольные команды оболочки, что позволяет выполнять сложные операции при входе в каталог.
Безопасность: Direnv требует явного разрешения на выполнение содержимого .envrc, что предотвращает случайное выполнение вредоносного кода.
Интеграция с другими инструментами: Direnv может работать в связке с такими инструментами, как pyenv, для управления версиями Python и создания виртуальных окружений.
Мы будем использовать его для настройки виртуального окружения Python, на основе файла .python-version, и его активации.
sudo apt-get install direnv
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrcИ сейчас нам так же понадобиться uv.
UV — это новый пакетный менеджер для Python, написанный на Rust, который предлагает высокую производительность и функциональность, заменяя традиционные инструменты, такие как pip, pip-tools и другие.
Основные особенности UV:
Высокая скорость: UV обеспечивает скорость установки и управления пакетами в 10-100 раз быстрее, чем pip, что делает его привлекательным для разработчиков, работающих с большими проектами.
Универсальный инструмент: UV объединяет функции нескольких инструментов, включая:
Установку и управление версиями Python.
Создание виртуальных окружений.
Управление зависимостями с использованием lock-файлов.
Совместимость: UV предоставляет интерфейс, совместимый с pip, что позволяет легко интегрировать его в существующие проекты без необходимости в значительной переработке кода.
Проектное управление: UV использует файл pyproject.toml для определения зависимостей и создает универсальный lock-файл (uv.lock), который упрощает управление зависимостями и их версиями.
Простота установки: UV можно установить как через pip, так и с помощью самостоятельных установщиков для различных операционных систем (macOS, Linux, Windows).
Поддержка работы с несколькими версиями Python: UV позволяет устанавливать и переключаться между различными версиями Python, что упрощает работу над проектами, требующими разные версии интерпретатора.
Создание виртуальных окружений: При добавлении новой зависимости UV автоматически создает виртуальное окружение в каталоге проекта, что упрощает настройку окружения для разработки.
Его можно установить как через cargo:
cargo install --git https://github.com/astral-sh/uv uvТак и почти через что угодно:
через curl:
curl -LsSf https://astral.sh/uv/install.sh | shчерез pip:
pip install uvВыбирайте любой понравившийся вариант.
Создадим директорию для проекта:
mkdir litestarcatscv
cd $_
uv initПапка с проектом должна выглядеть так:
.
├── README.md
├── hello.py
└── pyproject.tomlУстановим локальную версию питона:
pyenv install 3.13.1
pyenv local 3.13.1✅ Ожидаемый результат:
cat .python-versionВывод:
3.13.1Теперь создадим .envrc
Это файл, который, как говорилось выше, нужен для автоматической активации виртуального окружения. Здесь и далее я буду использовать neovim, вы же можете пользоваться любым удобным текстовым редактором:
nvim .envrcСкопируем туда следующий код и сохраняем:
# проверим что в директории лежит файл .python-version
if [ -f ".python-version" ] ; then
if [ ! -d ".venv" ] ; then
echo "Устанавливаем virtualenv для $(python -V)"
uv .venv
fi
echo "Активируем $(python -V) virtualenv"
source .venv/bin/activate
fi
# Показываем версию питона и путь к нему ${PATH}
echo "Virtualenv активирован для $(python -V)"
echo "$(which python)"
Если вы делали это в терминале, то можете увидеть следующую ошибку:
direnv: error .envrc is blocked. Run direnv allow to approve its content��то говорит нам о том, что нужно подтверждение того, что вы изменили файл, для предотвращения его автоматического выполнения. Эту команду потребуется выполнять только при изменения файла.
direnv allowТакже есть возможность отрывать этот файл на редактирование в дефолтном редакторе:
direnv editТогда после сохранения и закрытия файла всё это содержимое будет загружено автоматически без необходимости запуска direnv allow. А еще, вместо дефолтного редактора, для direnv edit, можно подключить свой любимый, с помощью добавления этой строки в ~/.zshrc:
export EDITOR="<yourbesteditor> --wait"Где вместо , укажите свой редактор.
И ещё один опциональный момент, чтобы в каждом проекте не добавлять эти файлы в gitignore, мы можем поместить их в глобальный gitignore — для того, чтобы ваши конфиденциальные данные, которые могут содержаться в этих файлах, случайно не утекли в сеть. Создайте файл:
touch ~/.gitignore_globalИ скопируйте туда следующие строки:
# Direnv files
.direnv
.envrc
# Virtual env
.venv
# Editor specific files and folders
.idea
.vscodeСохраните и закройте.
Вы также можете включить в него любые файлы и каталоги, которые относятся к вашей среде, редактору или операционной системе и которые не связаны с каким-либо конкретным проектом. Шаблоны таких файлов можно посмотреть, например, в гитхабе
И выполните команду:
git config --global core.excludesFile "~/.gitignore_global"Для проверки, что всё сделано правильно, выполните команду:
git config --global core.excludesFileОна должна вывести на экран путь к вашему глобальному gitignore файлу.
✅ Ожидаемый результат:
~/.gitignore_globalЕщё полезные фишки direnv

в контексте .envrc:
path_add - обычно для добавления пути мы используем export PATH=:$PATH, с помощью этой команды вы можете написать PATH_add my-new-path и он будет автоматически добавлен в ваш $PATH.
source_env - эта функция загружает другой .envrc указав путь или имя файла.
dot_env - загружает .env файл в текущую среду без необходимости установки каких-либо зависимостей. Таким образом, ваш проект занимает меньше места в каталоге.
watch_file [ ...] - добавляет один или несколько файлов в список наблюдения. direnv перезагрузит вашу оболочку при следующем запросе, если какой-либо из указанных файлов изменится. Больше фишек тут и тут
Примечание: вы также можете создавать собственные расширения, создавая bash файлы в папке ~/.config/direnv/direnvrc или ~/.config/direnv/lib/*.sh. Эти файлы загружаются до вашего .envrc и, таким образом, позволяют создавать собственные расширения для direnv.
Теперь у нас настроены инструменты, необходимые для управления окружением.
Проверим, что всё работает:
uv run hello.py✅ Ожидаемый результат:
Hello from litestarcatscv!Подключим litestar, granian и ruff к проекту
uv add litestar granian ruffLitestar — это современный и высокопроизводительный ASGI-фреймворк, который предназначен для создания API и веб-приложений.
Основные особенности Litestar:
Высокая производительность: Litestar разработан с акцентом на производительность, что позволяет создавать быстрые и отзывчивые приложения.
Гибкость и расширяемость: Фреймворк поддерживает плагины, что позволяет разработчикам добавлять новые функции и расширять возможности приложения без значительных усилий.
Интеграция с SQLAlchemy: Litestar предоставляет встроенную поддержку для SQLAlchemy, что упрощает работу с базами данных и позволяет использовать модели напрямую для валидации и сериализации данных.
Автоматическая генерация документации: Litestar автоматически генерирует документацию в формате OpenAPI, что облегчает интеграцию с фронтендом и делает API более доступным для разработчиков.
Поддержка асинхронного программирования: Фреймворк полностью поддерживает асинхронные операции, что позволяет эффективно обрабатывать множество запросов одновременно.
Система внедрения зависимостей: Litestar предлагает мощную систему внедрения зависимостей, которая помогает организовать код и уменьшить дублирование.
Валидация данных: Используя типизацию Python, Litestar обеспечивает строгую валидацию данных, что помогает минимизировать ошибки во время выполнения.
Поддержка различных типов хранилищ: Litestar может работать с различными хранилищами ключ-значение, что позволяет легко интегрировать сторонние расширения.
Обновим структуру проекта:
rm hello.py #он нам больше не нужен
mkdir src && nvim src/app.pyДобавим минимальный пример в app.py:
from litestar import Litestar, get@get("/")async def index() -> str: return "Hello, world!"app = Litestar([index,])Проверим работоспособность нашего приложения, запустим его с помощью granian:

Granian— это высокопроизводительный HTTP-сервер, разработанный на Rust для приложений Python. Он построен на основе библиотеки Hyper и предлагает ряд преимуществ для разработчиков, работающих с веб-приложениями.
Основные характеристики Granian:
Поддержка нескольких интерфейсов: Granian поддерживает ASGI, RSGI и WSGI интерфейсы, что позволяет использовать его с различными типами приложений и фреймворков.
Протоколы HTTP/1 и HTTP/2: Сервер реализует поддержку как для HTTP/1, так и для HTTP/2, что обеспечивает более эффективную передачу данных и улучшенную производительность.
Поддержка WebSockets: Granian позволяет работать с WebSockets, что делает его подходящим для разработки приложений реального времени.
Производительность: Granian предлагает стабильную производительность по сравнению с традиционными решениями, такими как Gunicorn и Uvicorn, избегая сложной зависимости от нескольких инструментов.
Конфигурация потоков и процессов: Granian позволяет настраивать количество процессов и потоков, что дает возможность оптимизировать использование ресурсов в зависимости от требований приложения.
Простота установки: Установить Granian можно с помощью pip
Запускаем сервер через Granian

uv run granian --interface asgi src/app:app✅ Ожидаемый результат:
Сервер запустится и при переходе на http://localhost:8000/ покажет Hello, world!.
Вывод:
INFO] Starting granian (main PID: 880817)
[INFO] Listening at: http://127.0.0.1:8000
[INFO] Spawning worker-1 with pid: 880818
[INFO] Started worker-1
[INFO] Started worker-1 runtime-1Автоматизация с Makefile

nvim MakefileПапка с проектом теперь выглядит так:
.
├── Makefile
├── README.md
├── hello.py
├── pyproject.toml
├── src
│ ├── __pycache__
│ │ └── app.cpython-313.pyc
│ └── app.py
└── uv.lockА теперь сделаем запуск разных команд через make.
Здесь как раз можно задействовать ruff.
Ruff — это современный и высокопроизводительный линтер для Python, разработанный на Rust. Он выделяется своей скоростью, гибкостью и широкими возможностями.
Основные характеристики Ruff:
Скорость: Ruff значительно быстрее традиционных линтеров, таких как Flake8, isort и Pylint. Он может выполнять анализ кода в 10-100 раз быстрее, что делает его идеальным для больших кодовых баз и обеспечивает быструю обратную связь.
Совместимость: Ruff служит заменой для нескольких популярных инструментов линтинга, включая Flake8, isort, pydocstyle и другие. Это позволяет разработчикам использовать один инструмент вместо множества, упрощая процесс линтинга.
Расширяемость: Ruff поддерживает создание пользовательских плагинов, что позволяет адаптировать его под специфические нужды проектов и команды.
Автоматические исправления: Linters могут автоматически исправлять множество ошибок, таких как удаление неиспользуемых импортов и реформация строк документации.
Поддержка множества правил: Ruff поддерживает более 500 правил линтинга и может быть настроен для работы с различными стилями кодирования.
Легкость в использовании: Интерфейс Ruff прост и интуитивно понятен, что делает его доступным даже для новичков.
Добавляем в файл:
.DEFAULT_GOAL := help
SHELL := bash
.PHONY : run test check format db-migrate db-upgrade help
# Запускаем проект
run:
uv run granian --interface asgi src/app:app
# Запускаем тесты
test:
uv run pytest
# Проверяем линтером
check:
@echo Running project linters...
uv run ruff check src
# Делаем автоформат
format:
@echo Running project linters...
uv run ruff --fix src
# Новая миграция
db-migrate:
alembic revision --autogenerate -m "New migration"
# Применить миграции
db-upgrade:
alembic upgrade head
# Список команд
help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'Теперь мы можем легко проверять и запускать наш проект с помощью:
make test
make check
make format
make runВывод

Итого, у нас получилось сделать минимальный пример, мы подготовили окружение, научились базово пользоваться pyenv, direnv, uv, make. И это уже отличный старт. А нашу заготовку мы будем улучшать в следующей части.
На этом пока что всё.
Читать 2-ую часть.
