Python Backend Developer: с нуля до Middle

Курс для изучения Python почти с нуля до уровня уверенного Middle backend-разработчика. Вы освоите сам язык, основы инженерных практик и ключевой стек для разработки API и сервисов: базы данных, web-фреймворки, тестирование, DevOps-базу и работу с асинхронностью.

1. Python Core: синтаксис, типы, функции, ООП и стандартная библиотека

Python Core: синтаксис, типы, функции, ООП и стандартная библиотека

Python — основной язык этого курса. В бэкенде на Python вы будете писать веб‑приложения и API, работать с базами данных, очередями, файловой системой, сериализацией данных (JSON), логированием, обработкой ошибок и конкурентностью. Всё это опирается на базовые знания Python Core: синтаксис, типы данных, функции, объектную модель, ООП и стандартную библиотеку.

В этой статье мы разберём фундамент, на который дальше будут «наслаиваться» фреймворки (например, FastAPI/Django), базы данных (PostgreSQL), инструменты (Docker) и практики (тестирование, CI/CD).

Как писать и запускать Python-код

Интерпретатор и файлы

Python — интерпретируемый язык: код выполняется интерпретатором python.

* Запуск файла: python app.py * Интерактивный режим (REPL): python и ввод команд по одной

Минимальный пример

Синтаксис: базовые конструкции

Комментарии и отступы

* Комментарий начинается с # и действует до конца строки. * Блоки кода задаются отступами, а не фигурными скобками.

Переменные: это имена, а не «коробки»

В Python переменная — это имя, которое ссылается на объект в памяти.

Здесь a и b ссылаются на один и тот же список.

!Иллюстрация модели «имена → объекты» и того, почему изменения в изменяемых объектах видны через разные переменные

Операторы и выражения

Арифметика: +, -, , /, // (целочисленное деление), % (остаток), ** (степень) * Сравнения: ==, !=, <, <=, >, >= * Логика: and, or, not * Принадлежность: in (например, "a" in "cat") Проверка того же объекта*: is (важно отличать от ==)

Управляющие конструкции

Условия

Циклы

for в Python перебирает элементы итерируемого объекта (например, списка). Итерируемый объект — это тот, по которому можно последовательно пройтись.

while выполняется, пока условие истинно.

Полезные конструкции:

* break — выйти из цикла * continue — перейти к следующей итерации

Генераторы списков (list comprehension)

Это компактный способ создать список из другого итерируемого объекта.

Типы данных: числа, строки, коллекции

Встроенные типы и изменяемость

Изменяемость означает: можно ли поменять объект «на месте», не создавая новый.

| Тип | Пример | Изменяемый | Где часто нужен в бэкенде | |---|---:|:---:|---| | int | 42 | нет | идентификаторы, счётчики | | float | 3.14 | нет | измерения, проценты (осторожно с точностью) | | bool | True | нет | флаги, проверки | | str | "api" | нет | URL, тексты, JSON-ключи | | list | [1, 2] | да | наборы элементов, результаты запросов | | tuple | (1, 2) | нет | неизменяемые структуры, ключи | | dict | { "a": 1 } | да | JSON-подобные данные, конфиги | | set | {1, 2} | да | уникальные значения, проверки | | NoneType | None | нет | отсутствие значения |

Официально про встроенные типы: Built-in Types — Python Documentation

Строки

Строки в Python — это Unicode.

Частые операции:

* len(s) — длина * s.lower(), s.upper() * s.strip() — убрать пробелы по краям * s.split(",") — разбить * ",".join(parts) — склеить

Списки, кортежи, множества

* list — когда нужна последовательность, которую вы будете менять * tuple — когда данные не должны меняться (или нужны как ключ словаря) * set — когда важна уникальность и быстрые проверки x in set

Словари (dict)

Словарь хранит пары ключ → значение.

В бэкенде dict — базовый формат для данных, близкий к JSON.

Функции: параметры, возвращаемые значения, области видимости

Функция — это именованный блок кода, который можно вызывать многократно.

Параметры: позиционные и именованные

Важно: значения параметров по умолчанию вычисляются один раз в момент определения функции. Поэтому нельзя использовать изменяемые значения (например, []) как безопасный дефолт.

Правильный паттерн:

args и *kwargs

args собирает лишние позиционные аргументы в кортеж *kwargs собирает лишние именованные аргументы в словарь

Это очень распространено в библиотечном и фреймворк‑коде.

Области видимости (scope)

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

Практическое правило:

* старайтесь передавать значения параметрами * минимизируйте использование глобальных переменных

Лямбда-функции

lambda — короткая анонимная функция (часто в сортировках и преобразованиях).

Декораторы: идея на пальцах

Декоратор — это функция, которая принимает функцию и возвращает новую функцию (обычно добавляя поведение). В веб‑фреймворках декораторы встречаются постоянно (роуты, авторизация, кэширование).

Документация: functools — Python Documentation

Исключения: как обрабатывать ошибки правильно

Исключение — это механизм сигнализировать об ошибке и прерывать обычный поток выполнения.

try / except / else / finally

* except выполняется, если в try случилось исключение указанного типа * else выполняется, если исключения не было * finally выполняется всегда (удобно для освобождения ресурсов)

В бэкенде корректная обработка исключений — основа надёжности API.

Модули, пакеты и импорт

Модуль

Модуль — это файл .py. Импорт выполняет код модуля и делает доступными его имена.

Пакет

Пакет — это директория с Python-кодом (обычно с файлом __init__.py).

Практический смысл для бэкенда:

* вы будете организовывать код по пакетам: app/, app/api/, app/services/, app/repositories/

Про импорт: The import system — Python Documentation

ООП в Python: классы, методы, наследование

ООП (объектно‑ориентированное программирование) помогает описывать сущности домена (например, пользователь, заказ), группировать данные и поведение, создавать расширяемую архитектуру.

Класс и объект

Термины:

класс* — «чертёж» объект (экземпляр)* — конкретное созданное значение этого класса * self — ссылка на текущий объект

Инкапсуляция и соглашения

В Python нет строгой приватности, но есть соглашение:

* name — публичное поле * _name — внутреннее поле (не для внешнего использования)

Наследование и полиморфизм

Наследование: один класс расширяет другой.

Полиморфизм в практике бэкенда означает: разные реализации ведут себя одинаково с точки зрения интерфейса (например, разные репозитории: in‑memory для тестов и PostgreSQL для продакшена).

Композиция чаще полезнее наследования

Композиция — когда класс содержит другие объекты и использует их.

Это часто делает архитектуру проще и гибче, чем глубокие иерархии наследования.

Специальные методы (dunder methods)

Методы вида __name__ называют dunder (double underscore). Они позволяют объектам работать со встроенными операциями языка.

Пример: __repr__ для удобного представления в логах.

Справочник: Data model — Python Documentation

dataclasses для «классов-данных»

Когда класс в основном хранит данные, удобно использовать dataclass.

Плюсы:

* автоматически создаётся __init__ * автоматически создаётся удобный __repr__

Документация: dataclasses — Python Documentation

Контекстные менеджеры и with

Контекстный менеджер гарантирует, что ресурс будет корректно освобождён, даже если возникла ошибка.

Классический пример — работа с файлами:

Здесь файл будет закрыт автоматически.

Стандартная библиотека: минимум, который нужен бэкенду

Стандартная библиотека — это модули, которые идут вместе с Python. Она огромная, но в бэкенде есть «костяк», который встречается постоянно.

Работа с путями и файлами: pathlib

pathlib предоставляет объектный интерфейс к путям (часто удобнее, чем os.path).

Документация: pathlib — Python Documentation

Даты и время: datetime

Документация: datetime — Python Documentation

JSON: json

В API вы постоянно сериализуете данные в JSON.

Документация: json — Python Documentation

Регулярные выражения: re

Регулярные выражения помогают искать и валидировать текст по шаблону (используйте умеренно, не усложняйте).

Документация: re — Python Documentation

Логирование: logging

print не подходит для продакшена. Логи должны иметь уровни, формат, вывод в файлы/системы.

Документация: logging — Python Documentation

Типизация: typing

Подсказки типов улучшают читаемость и помогают статическим анализаторам.

Документация: typing — Python Documentation

Полезные контейнеры и инструменты

* collections (например, defaultdict, deque): collections — Python Documentation * itertools для эффективных итераций: itertools — Python Documentation * contextlib для своих контекстных менеджеров: contextlib — Python Documentation

Стиль кода: читаемость и предсказуемость

В индустрии принято ориентироваться на PEP 8 (гайд по стилю). Это важно, потому что бэкенд‑код читают и поддерживают командой.

* Гайд: PEP 8 — Style Guide for Python Code

Базовые привычки:

* осмысленные имена (без a, b, tmp, если можно лучше) * небольшие функции * явная обработка ошибок * минимум побочных эффектов (когда функция «тайно» меняет внешние данные)

Итог

К этому моменту у вас есть фундамент:

* синтаксис и управление потоком * модель «имена ссылаются на объекты» и разница между == и is * основные типы данных и коллекции функции, параметры, args/**kwargs, декораторы на уровне идеи * исключения и гарантии finally * основы модулей/пакетов * ООП, dataclass, специальные методы * ключевые модули стандартной библиотеки для бэкенда

Дальше этот фундамент будет применяться к реальным бэкенд‑задачам: проектная структура, HTTP, работа с БД, миграции, конфигурация, логирование, тестирование, асинхронность и развёртывание.

2. Инструменты разработчика: Git, Linux, виртуальные окружения, packaging и качество кода

Инструменты разработчика: Git, Linux, виртуальные окружения, packaging и качество кода

После блока Python Core у вас уже есть язык и базовые конструкции. Но в работе Python backend‑разработчика почти половина успеха — это не «знать синтаксис», а уметь:

  • управлять исходным кодом в Git
  • уверенно работать в Linux и терминале
  • изолировать зависимости проекта (виртуальные окружения)
  • корректно устанавливать и фиксировать зависимости (packaging)
  • поддерживать качество кода автоматически (форматирование, линтеры, типизация)
  • Эта статья — про минимальный, но практичный набор инструментов, который нужен, чтобы писать код в команде и без боли запускать проекты локально и на сервере.

    Git как основа командной разработки

    Git — распределённая система контроля версий. Она хранит историю изменений проекта и позволяет параллельно работать нескольким людям, безопасно объединяя изменения.

    Ключевые понятия:

  • репозиторий — папка проекта с историей изменений
  • коммит — сохранённый снимок изменений с сообщением
  • ветка — независимая линия разработки
  • удалённый репозиторий — репозиторий на сервере (например, GitHub)
  • pull request / merge request — запрос на вливание ветки в основную ветку с код‑ревью
  • Базовый рабочий цикл

  • git clone <url> — скачать репозиторий
  • git checkout -b feature/auth — создать ветку под задачу
  • правки в коде
  • git status — посмотреть изменённые файлы
  • git add . — добавить изменения в индекс
  • git commit -m "Add login endpoint" — создать коммит
  • git push -u origin feature/auth — отправить ветку на сервер
  • открыть pull request, пройти ревью, смержить
  • !Схема показывает, как ветка с задачей попадает в main через pull request

    Полезные источники:

  • Pro Git (книга)
  • Git Reference
  • Что важно в коммитах

    Коммит — это единица истории. Хорошие привычки:

  • коммит должен решать одну логическую задачу
  • сообщение коммита должно объяснять что сделано и зачем
  • старайтесь коммитить часто и небольшими порциями
  • Частый стиль сообщений:

  • Add user registration
  • Fix token refresh bug
  • Refactor repository layer
  • git diff, git log, откат изменений

    Команды, которые вы будете использовать постоянно:

  • git diff — посмотреть разницу до добавления в коммит
  • git diff --staged — разница того, что уже добавили через git add
  • git log --oneline --graph --decorate — краткая история
  • Откаты (важно понимать разницу):

  • git restore <file> — отменить изменения в рабочем каталоге для файла (вернуть к последнему коммиту)
  • git restore --staged <file> — убрать файл из индекса (после git add)
  • git revert <commit> — создать новый коммит, который отменяет изменения указанного коммита (без переписывания истории, безопасно для shared‑веток)
  • .gitignore

    .gitignore — файл со списком того, что не надо коммитить.

    Обычно игнорируют:

  • виртуальные окружения: .venv/, venv/
  • кеши Python: __pycache__/, *.pyc
  • файлы IDE: .idea/, .vscode/
  • локальные секреты и конфиги: .env (чаще не коммитят)
  • Готовые шаблоны:

  • gitignore для Python (GitHub)
  • merge и rebase простыми словами

    Обе операции нужны, чтобы интегрировать изменения из одной ветки в другую.

  • merge делает коммит слияния и сохраняет «ветвление» в истории
  • rebase «переносит» ваши коммиты на новую базу, делая историю более линейной
  • Практическое правило для начинающих:

  • в общих ветках (например, main) избегайте rebase по уже опубликованной истории
  • rebase удобен для локальной подготовки ветки перед pull request, чтобы убрать лишние «пустые» merge‑коммиты
  • Если в вашей команде есть правило (например, squash merge), придерживайтесь его.

    Linux и терминал: рабочая среда бэкенда

    Большинство production‑серверов — это Linux. Даже если вы пишете код на Windows/macOS, вам нужно уверенно чувствовать себя в терминале.

    Файловая система и навигация

    Основные команды:

  • pwd — текущая директория
  • ls -la — список файлов (включая скрытые)
  • cd /path — перейти в директорию
  • mkdir app — создать директорию
  • touch app.py — создать пустой файл
  • cp, mv, rm — копировать, перемещать, удалять
  • Полезные приёмы:

  • history — история команд
  • автодополнение по Tab
  • поиск по истории: Ctrl+R
  • Справка по командам:

  • man ls
  • ls --help
  • Права доступа и исполняемые файлы

    В Linux у файлов есть права:

  • r — чтение
  • w — запись
  • x — выполнение
  • Команда chmod меняет права, например:

    Это делает файл исполняемым.

    Полезно понимать:

  • кто владелец файла
  • к какой группе относится
  • какие права у владельца, группы и остальных
  • Процессы и порты

    Backend‑сервис — это процесс, который часто слушает порт.

    Команды:

  • ps aux — список процессов
  • top или htop — мониторинг ресурсов
  • kill <pid> — завершить процесс
  • ss -tulpn — какие процессы слушают порты (частая замена netstat)
  • Проверка доступности сервиса:

    curl — один из главных инструментов backend‑разработчика для тестирования HTTP.

    Документация:

  • curl manual
  • Переменные окружения

    Переменные окружения — это параметры, которые передаются процессу извне. В бэкенде в них часто хранят:

  • строку подключения к БД
  • секреты (ключи, токены)
  • настройки окружения (dev/stage/prod)
  • Пример:

    Посмотреть переменную:

    Важно: секреты не должны попадать в Git.

    SSH: как заходят на сервер

    SSH — протокол для безопасного подключения к серверу.

  • подключение: ssh user@server
  • копирование файлов: scp file user@server:/path
  • Хорошая практика:

  • использовать ключи вместо пароля
  • не хранить приватный ключ в доступных местах
  • Справка:

  • OpenSSH Manual Pages
  • Виртуальные окружения: изоляция зависимостей

    В Python зависимости устанавливаются в окружение. Если устанавливать всё «в систему», проекты начнут конфликтовать между собой (разные версии библиотек).

    Виртуальное окружение — это отдельная директория со своим Python и пакетами.

    venv: стандартный способ

    Создание:

    Активация:

  • Linux/macOS:
  • Windows PowerShell:
  • Проверка:

    Выход:

    Документация:

  • venv — Python Documentation
  • pip: установка пакетов

    pip — стандартный установщик пакетов Python.

    Примеры:

    Полезные команды:

  • python -m pip list — список установленных пакетов
  • python -m pip show <name> — информация о пакете
  • python -m pip freeze — вывести зависимости с версиями
  • Документация:

  • pip documentation
  • Packaging: как проект описывает зависимости и как он устанавливается

    Слово packaging в Python означает набор практик и стандартов, как:

  • описывать зависимости
  • собирать проект
  • публиковать и устанавливать пакеты
  • Для backend‑разработчика ключевой навык — уметь воспроизводимо установить проект на новой машине.

    pyproject.toml: единый файл конфигурации проекта

    Современный стандарт — хранить метаданные и зависимости в pyproject.toml.

    Этот файл используется разными инструментами (например, Poetry, Hatch, PDM), а также системами сборки.

    Справка:

  • PEP 518 — Specifying Minimum Build System Requirements
  • Python Packaging User Guide
  • requirements.txt и фиксация версий

    Во многих проектах всё ещё используют requirements.txt.

    Типичные варианты:

  • строгая фиксация: fastapi==0.115.0
  • диапазон: fastapi>=0.110,<0.116
  • Практический смысл:

  • строгая фиксация повышает воспроизводимость
  • диапазоны облегчают обновления, но требуют аккуратности
  • Команда для установки:

    Разница между библиотекой и приложением

  • приложение (web‑сервис) обычно не публикуют как пакет в публичный индекс, его разворачивают как проект
  • библиотека предназначена для переиспользования и может публиковаться как пакет
  • Даже если вы пишете приложение, структура packaging помогает:

  • чётко описать зависимости
  • стандартизировать команды
  • упростить CI/CD
  • Poetry как популярный инструмент для проектов

    Poetry объединяет:

  • управление зависимостями
  • создание виртуального окружения
  • сборку проекта
  • Установка и документация:

  • Poetry Documentation
  • Минимальная логика работы:

  • poetry init или готовый pyproject.toml
  • poetry add fastapi — добавить зависимость
  • poetry install — установить зависимости
  • poetry run python app.py — запуск команды внутри окружения
  • Если в команде принят pip + requirements.txt, используйте его. Если принят Poetry — используйте Poetry. Важно не инструмент, а предсказуемая установка.

    !Диаграмма показывает, как зависимости проходят путь от описания до запуска и CI

    Качество кода: форматирование, линтинг, типы, хуки

    Качество кода в команде поддерживают автоматикой. Это снижает количество ошибок и ускоряет ревью.

    Термины:

  • форматтер — приводит код к единому стилю
  • линтер — ищет потенциальные ошибки и плохие практики
  • type checker — проверяет подсказки типов
  • pre-commit hook — запуск проверок перед коммитом
  • Форматирование: Black

    Black — популярный форматтер Python. Его идея: минимум настроек, один стиль для всех.

  • Black documentation
  • Запуск обычно выглядит так:

    Эффект:

  • исчезают споры про пробелы/переносы
  • ревью концентрируется на логике, а не на стиле
  • Линтинг: Ruff

    Ruff — быстрый линтер, который покрывает множество правил и часто заменяет связку из нескольких инструментов.

  • Ruff documentation
  • Пример:

    Даже если вы используете Black, Ruff полезен как «детектор проблем».

    Типизация: mypy или pyright

    Подсказки типов (из модуля typing) помогают:

  • лучше понимать интерфейсы функций
  • ловить ошибки несовместимых типов до запуска
  • делать код безопаснее при рефакторинге
  • Инструменты:

  • mypy documentation
  • Pyright documentation
  • Важно: типизация не заменяет тесты и не делает код «магически правильным», но сильно помогает в больших кодовых базах.

    pre-commit: проверки перед коммитом

    pre-commit позволяет настроить автоматический запуск инструментов перед созданием коммита.

  • pre-commit.com
  • Типичный набор хуков:

  • форматирование (Black и/или Ruff format)
  • линтинг (Ruff check)
  • проверка, что нет лишних пробелов
  • проверка, что файлы заканчиваются переводом строки
  • Идея проста: лучше поймать проблемы до того, как они попадут в историю Git и на ревью.

    Автоматизация в CI

    CI (continuous integration) — это запуск проверок на сервере при пуше/PR.

    Обычно в CI гоняют:

  • линтер
  • форматтер в режиме проверки
  • type checker
  • тесты
  • Если вы используете GitHub:

  • GitHub Actions Documentation
  • Минимальный практичный стандарт проекта

    Ниже пример того, что обычно считается «базовой гигиеной» Python backend‑проекта:

  • Git: ветки под задачи, pull request, понятные коммиты
  • Linux: уверенная навигация, понимание процессов/портов, умение использовать curl
  • окружение: .venv или Poetry‑окружение, не коммитится в репозиторий
  • зависимости: фиксируются и устанавливаются одной командой
  • качество: форматирование и линтинг запускаются локально и в CI
  • Итог

    Вы освоили инструменты, которые превращают знание Python в реальную профессиональную практику:

  • Git как способ безопасно вести историю и работать в команде
  • Linux и терминал как среду, где живут backend‑сервисы
  • виртуальные окружения как обязательную изоляцию зависимостей
  • packaging как способ воспроизводимо устанавливать проект
  • автоматические проверки качества кода как стандарт индустрии
  • Дальше эти навыки будут постоянно использоваться, когда мы перейдём к веб‑разработке, базам данных, тестированию и развёртыванию.

    3. Backend основы: HTTP, REST, FastAPI/Django, ORM, SQL и PostgreSQL

    Backend основы: HTTP, REST, FastAPI/Django, ORM, SQL и PostgreSQL

    После того как вы освоили Python Core и базовые инструменты разработчика (Git, Linux, виртуальные окружения, packaging и качество кода), можно переходить к тому, ради чего обычно и учат Python в бэкенде: создавать HTTP‑сервисы, проектировать API, работать с базой данных и писать код так, чтобы его было удобно поддерживать.

    В этой статье вы разберёте базовую связку, которая встречается в подавляющем большинстве Python‑бэкенд проектов:

  • HTTP как транспорт
  • REST как стиль проектирования API
  • FastAPI и Django как основные фреймворки
  • SQL как язык запросов
  • PostgreSQL как основная реляционная БД
  • ORM как мост между кодом и таблицами
  • !Общая картина: как запрос проходит через фреймворк, код и базу данных

    HTTP: как клиент и сервер договариваются

    HTTP (HyperText Transfer Protocol) — протокол, по которому клиент (браузер, мобильное приложение, другой сервер) общается с вашим сервисом.

    Модель запрос–ответ

    В HTTP почти всё укладывается в простую модель:

  • Клиент отправляет HTTP request (запрос)
  • Сервер возвращает HTTP response (ответ)
  • Запрос включает:

  • метод (например, GET, POST)
  • URL (например, /users/42)
  • заголовки (headers)
  • тело (body) — необязательно (например, JSON в POST)
  • Ответ включает:

  • статус‑код (например, 200)
  • заголовки
  • тело (например, JSON)
  • Методы HTTP

    Основные методы в API:

  • GET — получить данные
  • POST — создать ресурс или выполнить команду
  • PUT — полностью заменить ресурс
  • PATCH — частично обновить ресурс
  • DELETE — удалить ресурс
  • Важно: методы — это не «магия», а договорённость. Технически можно делать что угодно, но индустрия придерживается смыслов выше.

    Статус‑коды

    Коды статуса — это быстрый сигнал клиенту, что произошло.

    | Группа | Примеры | Смысл | |---|---|---| | 2xx | 200 OK, 201 Created | успешно | | 3xx | 301 Moved Permanently, 302 Found | перенаправление | | 4xx | 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 422 Unprocessable Entity | ошибка на стороне клиента | | 5xx | 500 Internal Server Error, 503 Service Unavailable | ошибка на стороне сервера |

    Практическое правило для бэкенда: ошибки валидации и неправильный запрос — это 4xx, падения и баги — это 5xx.

    Заголовки и контент‑типы

    Заголовки передают метаданные. Для API особенно важны:

  • Content-Type: что лежит в теле запроса или ответа (например, application/json)
  • Accept: что клиент ожидает в ответе
  • Authorization: данные аутентификации (например, Bearer <token>)
  • Как тестировать HTTP руками

    Основа из предыдущей статьи про Linux и терминал здесь сразу пригодится: используйте curl.

    Флаг -i показывает заголовки ответа.

    Документация:

  • HTTP Semantics (RFC 9110)
  • curl manual
  • REST: стиль проектирования API

    REST — это набор принципов, как проектировать API вокруг ресурсов.

    Ресурсы и маршруты

    Ресурс — это сущность предметной области. Примеры:

  • users
  • orders
  • products
  • Обычно используют правила:

  • коллекция: GET /users
  • один объект: GET /users/{id}
  • создание: POST /users
  • обновление: PATCH /users/{id}
  • удаление: DELETE /users/{id}
  • Идемпотентность

    Идемпотентность означает: повторный запрос даёт тот же эффект, что и первый.

  • GET идемпотентен (не должен менять состояние)
  • PUT обычно идемпотентен (повторная полная замена приводит к тому же состоянию)
  • DELETE идемпотентен по смыслу (удалить два раза всё равно приводит к отсутствию ресурса)
  • POST обычно не идемпотентен (повтор может создать две записи)
  • Эта идея важна при ретраях, прокси и сбоях сети.

    Версионирование API

    Частый практический подход — версионировать API в пути:

  • /api/v1/...
  • /api/v2/...
  • Это не единственный вариант (можно через заголовки), но он самый понятный и распространённый.

    FastAPI и Django: что выбрать и почему

    Python‑бэкенд чаще всего строят на одном из двух фреймворков:

  • FastAPI — современный, быстрый, хорошо подходит для API, активно использует типизацию
  • Django — батарейки‑в‑комплекте: админка, ORM, миграции, шаблоны, формы, аутентификация
  • Когда чаще выбирают FastAPI

  • чистые JSON API
  • микросервисы
  • высокая скорость разработки API за счёт автогенерации OpenAPI/Swagger
  • желание иметь больше контроля над архитектурой (собирать проект из компонентов)
  • Документация:

  • FastAPI Documentation
  • Минимальный пример:

    Запуск обычно делают через uvicorn:

    Когда чаще выбирают Django

  • монолитные приложения
  • нужна админка и готовая модель пользователей
  • много CRUD‑логики
  • команда хочет «единый стандартный путь»
  • Документация:

  • Django Documentation
  • Важно: Django отлично подходит и для API, особенно в связке с Django REST Framework.

    Документация:

  • Django REST framework
  • Ключевая мысль

    Фреймворк решает задачи:

  • маршрутизация (какая функция/метод обработает URL)
  • сериализация (как превратить данные в JSON)
  • валидация входа
  • обработка ошибок
  • интеграция с БД
  • Но качество бэкенда в итоге определяется тем, насколько грамотно вы проектируете доменную логику, хранение данных и интерфейсы.

    SQL и реляционная модель: как реально хранятся данные

    SQL — язык запросов к реляционным базам данных. Реляционная модель — это таблицы, строки и столбцы.

    Таблицы, строки, ключи

  • таблица — набор однотипных сущностей (например, users)
  • строка — один объект (например, пользователь с id = 42)
  • первичный ключ (primary key) — уникальный идентификатор строки
  • внешний ключ (foreign key) — ссылка на строку в другой таблице
  • Пример схемы:

  • users(id, email)
  • orders(id, user_id, total) где orders.user_id ссылается на users.id
  • Базовые операции CRUD на SQL

    Фильтрация, сортировка, пагинация

    Практический смысл LIMIT/OFFSET:

  • LIMIT ограничивает число строк
  • OFFSET пропускает первые строки
  • У OFFSET есть минусы на больших таблицах, но как стартовая пагинация он встречается часто.

    JOIN: как объединяют таблицы

    JOIN — одна из ключевых причин, почему реляционные базы так удобны для бизнес‑данных.

    PostgreSQL: стандарт де-факто для Python-бэкенда

    PostgreSQL — мощная реляционная база данных с сильной репутацией надёжности и функциональности.

    Документация:

  • PostgreSQL Documentation
  • Что важно знать бэкенд‑разработчику

  • PostgreSQL строго соблюдает типы данных и ограничения
  • хорошо работает с транзакциями
  • поддерживает индексы, расширения, JSONB и многое другое
  • Индексы: зачем они

    Индекс ускоряет поиск по колонке, но замедляет вставки и обновления (потому что индекс тоже надо обновлять).

    Типичная практика:

  • индексировать колонки, по которым часто фильтруются (WHERE) или соединяются (JOIN ON)
  • не индексировать «всё подряд» без замеров
  • Транзакции

    Транзакция — это группа операций, которая выполняется как единое целое:

  • либо применяются все изменения
  • либо не применяется ничего
  • Это защищает от частичных обновлений, когда бизнес‑операция состоит из нескольких запросов.

    Пример на SQL:

    Если между запросами произойдёт ошибка, вместо COMMIT делают ROLLBACK.

    Подключения и пул

    Открывать новое соединение с БД на каждый запрос дорого. Поэтому используют connection pool (пул соединений): заранее созданный набор соединений, которые переиспользуются.

    В веб‑приложениях пул обычно настраивается на уровне драйвера или ORM.

    ORM: зачем он нужен и где его границы

    ORM (Object-Relational Mapping) — слой, который позволяет работать с таблицами как с объектами Python.

    Плюсы ORM:

  • меньше «сырого» SQL в коде
  • удобнее описывать модели и связи
  • проще делать типовые CRUD‑операции
  • миграции схемы часто идут рядом
  • Минусы ORM:

  • можно случайно сделать очень неэффективные запросы
  • сложные запросы иногда проще и понятнее на SQL
  • нужно понимать, что реально происходит в базе
  • Главная профессиональная привычка: использовать ORM, но уметь читать и писать SQL.

    ORM в Django

    Django ORM встроен и является важной частью фреймворка.

    Документация:

  • Django ORM (QuerySet API)
  • ORM в FastAPI

    FastAPI сам по себе ORM не содержит, но обычно используют:

  • SQLAlchemy
  • SQLModel (надстройка над SQLAlchemy)
  • Документация:

  • SQLAlchemy Documentation
  • Миграции: как безопасно менять схему БД

    Миграция — это версионируемое изменение схемы базы данных (создать таблицу, добавить колонку, изменить индекс).

    Почему это часть бэкенда:

  • схема БД развивается вместе с кодом
  • продакшен‑база не создаётся заново «с нуля» на каждый деплой
  • изменения должны быть воспроизводимыми
  • В Django миграции встроены.

    Документация:

  • Django Migrations
  • В мире SQLAlchemy часто используют Alembic.

    Документация:

  • Alembic Documentation
  • Контракты API: OpenAPI и документация

    Современные API выигрывают, когда у них есть формальный контракт:

  • список эндпоинтов
  • схемы входных и выходных данных
  • коды ошибок
  • FastAPI автоматически генерирует OpenAPI‑схему.

    Документация:

  • OpenAPI Specification
  • В Django обычно используют инструменты генерации схемы (в Django REST Framework есть популярные решения), но концепция одна: клиентам и команде нужен единый контракт.

    Практические рекомендации уровня Junior → Middle

    Не смешивайте слои

    Хорошая минимальная структура мыслей:

  • HTTP‑слой: роуты, статусы, сериализация
  • Бизнес‑логика: правила предметной области
  • Доступ к данным: ORM/SQL, транзакции
  • Если бизнес‑логика «размазана» по роутам и моделям ORM, проект быстро становится хрупким.

    Делайте валидацию данных явной

    Проверка входных данных должна происходить до попытки записать их в базу.

    Логируйте ошибки и ключевые события

    Навык из Python Core и статьи про инструменты здесь становится обязательным: используйте logging, а не print.

    Всегда думайте о данных

    Для каждой сущности задавайте вопросы:

  • какие уникальные ограничения нужны (например, email)
  • какие связи с другими сущностями
  • какие запросы будут самыми частыми
  • нужны ли индексы
  • Итог

    Вы собрали базовую картину Python‑бэкенда:

  • HTTP определяет, как запросы и ответы проходят между клиентом и сервером
  • REST помогает проектировать API вокруг ресурсов и предсказуемых правил
  • FastAPI и Django решают типовые задачи веб‑разработки, но отличаются философией
  • SQL и PostgreSQL — основа хранения бизнес‑данных
  • ORM ускоряет разработку, но не отменяет необходимость понимать SQL
  • миграции и транзакции — ключ к надёжности данных
  • Дальше в курсе эти знания превратятся в практику: проектирование реального API, подключение PostgreSQL, написание моделей, миграций, тестов, а затем развёртывание и эксплуатация.

    4. Надёжность и масштабирование: тестирование, безопасность, кеши, очереди, асинхронность

    Надёжность и масштабирование: тестирование, безопасность, кеши, очереди, асинхронность

    В прошлых блоках вы освоили основу: Python Core, инструменты разработчика (Git, Linux, окружения, качество кода) и фундамент бэкенда (HTTP, REST, FastAPI/Django, ORM, SQL, PostgreSQL). Теперь следующий шаг до уровня уверенного Junior+ и Middle — научиться делать сервисы:

  • надёжными: они предсказуемо работают, их легко менять, ошибки быстро обнаруживаются и не приводят к потере данных
  • масштабируемыми: выдерживают рост нагрузки и функциональности без постоянного “переписывания с нуля”
  • В этой статье мы разберём практический набор тем, который в реальных проектах идёт “в комплекте”: тестирование, безопасность, кеширование, очереди и асинхронность.

    !Общая картина: где в системе появляются кеш и очередь и как они помогают надёжности и масштабированию

    Надёжность как цель разработки

    Надёжность в бэкенде обычно означает:

  • корректность: сервис выполняет бизнес-правила и не портит данные
  • устойчивость: ошибки обрабатываются, сервис деградирует контролируемо
  • воспроизводимость: на новой машине/сервере всё поднимается одинаково
  • наблюдаемость: по логам и метрикам можно понять, что происходит
  • Часть этого вы уже начали в прошлых статьях:

  • структурирование кода, обработка исключений, logging
  • повторяемая установка зависимостей
  • понимание HTTP статусов и контрактов API
  • понимание SQL, транзакций, индексов
  • Дальше мы добавим “страховочные механизмы” вокруг вашего сервиса.

    Тестирование: как перестать бояться изменений

    Тестирование — это способ быстро проверять, что сервис продолжает работать после изменений. В бэкенде тесты особенно важны, потому что:

  • баг может проявиться только на редком наборе данных
  • “ручная проверка через Postman” плохо масштабируется
  • сервис почти всегда зависит от БД, внешних API, очередей, кешей
  • Виды тестов

  • Unit-тесты: проверяют маленькие куски логики (функции/методы) без сети и без БД
  • Интеграционные тесты: проверяют взаимодействие с реальными компонентами (например, PostgreSQL)
  • End-to-end тесты: проверяют систему целиком через HTTP, максимально близко к продакшену
  • Практичный ориентир: чем тест “выше” и ближе к реальной системе, тем он медленнее и дороже в поддержке. Поэтому обычно делают много unit-тестов и меньше интеграционных.

    Pytest как стандарт де-факто

    В Python-бэкенде чаще всего используют pytest.

    Документация: Pytest Documentation

    Ключевые идеи:

  • тест — это обычная функция test_*
  • assert выражает ожидание
  • fixtures помогают поднимать и переиспользовать окружение
  • Пример unit-теста:

    Fixtures: подготовка данных и зависимостей

    Fixtures дают контроль над тестовым окружением: подготовить объект, подключение, клиент, тестовые данные.

    Плюс fixtures — они уменьшают копипаст и делают тесты стабильнее.

    Моки: когда зависимость слишком тяжёлая

    Если ваш код ходит во внешний сервис (оплата, SMS, стороннее API), в unit-тестах это обычно мокают — подменяют реализацию “заглушкой”. Важно: мокайте границы системы (HTTP-клиент, репозиторий), а не внутренние функции без необходимости.

    Для моков часто используют стандартный модуль unittest.mock.

    Документация: unittest.mock — Python Documentation

    Тестирование HTTP API

    #### FastAPI

    FastAPI предоставляет удобный тест-клиент.

    Документация: Testing — FastAPI

    Пример:

    #### Django

    У Django встроен тестовый клиент и инфраструктура.

    Документация: Testing in Django

    База данных в тестах

    Проверка кода, который пишет в PostgreSQL, почти всегда требует интеграционных тестов.

    Ключевые принципы:

  • тестовая БД должна быть отдельной от dev/production
  • тесты должны быть детерминированными: одинаковый результат при повторном запуске
  • очистка данных должна быть автоматической (транзакции, роллбек, пересоздание схемы)
  • Для Django это часто “из коробки”. Для FastAPI/SQLAlchemy обычно настраивают отдельный движок и транзакции на тест.

    Что проверять в первую очередь

    Практичный список “обязательных” проверок для API:

  • валидация входных данных (неправильный JSON, неправильные типы, пустые поля)
  • коды ответов (400/401/403/404/409/422) и формат ошибок
  • транзакционность важных операций (например, создание заказа + списание остатков)
  • авторизация (доступ к чужим ресурсам запрещён)
  • Безопасность: базовая гигиена Python-бэкенда

    Безопасность — это не “одна фича”, а системная работа. Ошибка безопасности часто хуже обычного бага: она может привести к утечке данных или захвату аккаунтов.

    Полезная база для понимания типовых рисков: OWASP Top 10

    Валидация и нормализация входных данных

    Правило: не доверяйте входу — ни JSON телу, ни query-параметрам, ни заголовкам.

    Практика:

  • валидируйте типы, диапазоны, длины
  • нормализуйте строки (например, email в lower-case, убирайте пробелы)
  • для API используйте схемы (Pydantic в FastAPI, serializers в DRF)
  • SQL-инъекции и безопасные запросы

    SQL-инъекция появляется, когда вы “склеиваете SQL строку руками” из пользовательского ввода.

    Правильно:

  • используйте ORM
  • если пишете сырой SQL, используйте параметризацию драйвера/ORM
  • Неправильно:

    Аутентификация и хранение паролей

    Пароли нельзя хранить в базе “как есть” и нельзя “хешировать” простыми функциями вроде SHA-256 без специальных механизмов.

    Правильный подход:

  • хранить хеш пароля, созданный адаптивным алгоритмом (например, bcrypt/argon2)
  • использовать готовые решения фреймворков (Django Auth) или проверенные библиотеки
  • В Django это встроено.

    Документация: Password management in Django

    Авторизация: кто что может

    Аутентификация отвечает на вопрос “кто ты?”, авторизация — “что тебе разрешено?”.

    Типовые проверки:

  • роль (admin/user)
  • принадлежность ресурса (пользователь может читать/менять только свои объекты)
  • Критичная ошибка: “IDOR” (Insecure Direct Object Reference) — когда пользователь меняет id в URL и получает чужие данные.

    Секреты и переменные окружения

    Секреты (ключи, пароли, токены) нельзя хранить в Git.

    Практика:

  • хранить секреты в переменных окружения
  • использовать .env только локально и добавлять его в .gitignore
  • Это напрямую связано с тем, что вы уже изучили про Linux и окружение.

    HTTPS, cookies, CORS и CSRF

  • HTTPS обязателен в продакшене: он защищает данные в пути между клиентом и сервером
  • CORS — политика браузера, ограничивающая запросы к вашему API с чужих доменов
  • CSRF — атака на браузерные приложения при использовании cookies и сессий
  • Важно понимать общий принцип: безопасность зависит от того, кто ваш клиент.

  • Если у вас “чистое” API для мобильного приложения с токенами — CSRF часто не актуален, но CORS может быть ограничен
  • Если у вас браузерное приложение на cookies — CSRF защита становится обязательной
  • FastAPI про CORS: CORS — FastAPI

    Rate limiting и защита от злоупотреблений

    Даже корректный функционал можно “сломать” большим числом запросов.

    Применяют:

  • rate limiting на IP/пользователя
  • ограничения размера тела запроса
  • таймауты
  • Обычно это делают на уровне reverse proxy (например, Nginx) и/или приложения.

    Кеширование: скорость и снижение нагрузки

    Кеш — это сохранённый результат, который можно быстро вернуть без повторного вычисления или запроса в БД.

    Где бывает кеш

  • на клиенте и прокси: HTTP-кеширование через заголовки
  • в приложении: кеширование результатов функций/запросов
  • в отдельном хранилище: Redis/Memcached
  • Redis как типовой выбор

    Redis часто используют как внешний кеш.

    Документация: Redis Documentation

    Типовые сценарии:

  • кеширование ответа/объекта по ключу
  • хранение сессий/токенов (в зависимости от схемы)
  • rate limiting (счётчики)
  • Базовый паттерн cache-aside

    Идея:

  • попробовать взять значение из кеша
  • если там нет — загрузить из БД
  • положить в кеш с TTL
  • Важно: кеш должен иметь TTL (время жизни), иначе вы рискуете хранить устаревшие данные бесконечно.

    Инвалидация: главная сложность кешей

    Кеш ускоряет чтение, но усложняет консистентность.

    Типовые стратегии:

  • короткий TTL и принятие “слегка устаревших данных”
  • инвалидация по событию (после обновления сущности чистить ключ)
  • версионирование ключей (сменили версию — старые ключи больше не читаются)
  • Частые ошибки с кешами

  • кешировать без понимания “что будет при обновлении данных”
  • кешировать слишком крупные объекты
  • кешировать “всё подряд”, создавая непредсказуемое поведение
  • не учитывать cache stampede: когда ключ истёк и много запросов одновременно ударяют в БД
  • Очереди и фоновые задачи: отделяем “быстро ответить” от “долго сделать”

    Очередь позволяет API быстро принять запрос, а тяжёлую работу выполнить в фоне.

    Когда нужна очередь

  • отправка email/SMS
  • генерация отчётов
  • обработка изображений/видео
  • синхронизация с внешними сервисами
  • любые операции, где пользователь не обязан ждать завершения
  • Брокер и воркеры

    Минимальная модель:

  • broker (брокер сообщений) хранит задачи (RabbitMQ/Redis и другие)
  • worker процессы забирают задачи и выполняют
  • Популярная связка в Python:

  • Celery + RabbitMQ/Redis
  • Документация:

  • Celery Documentation
  • RabbitMQ Documentation
  • Ретраи, идемпотентность и dead letter

    Фоновые задачи почти всегда требуют продуманной обработки ошибок.

    Ключевые понятия:

  • retry: повторить задачу через некоторое время
  • идемпотентность: повторное выполнение не должно портить данные (важно при ретраях)
  • dead letter queue: место, куда попадают задачи, которые не удалось выполнить после всех попыток
  • Практический пример риска:

  • задача “списать деньги” должна быть устроена так, чтобы повторный запуск не списал дважды
  • Частый паттерн — хранить “ключ идемпотентности” (например, operation_id) и проверять, была ли операция уже применена.

    Очередь не заменяет транзакции

    Очередь помогает с асинхронной обработкой, но корректность данных по-прежнему опирается на:

  • транзакции в БД
  • уникальные ограничения
  • чёткие бизнес-инварианты
  • Асинхронность: как обслуживать больше I/O без лишних потоков

    Асинхронность в Python чаще всего используют в веб-сервисах, чтобы эффективнее работать с I/O (ожидание сети, БД, файлов), а не чтобы ускорять CPU-вычисления.

    Что такое async/await

    asyncio — стандартная библиотека для асинхронного ввода/вывода.

    Документация: asyncio — Python Documentation

    Модель простая:

  • есть event loop (цикл событий)
  • пока одна корутина ждёт I/O, loop переключается на другую
  • !Иллюстрация, почему async полезен при большом числе одновременных запросов

    Async в FastAPI

    FastAPI поддерживает async def-обработчики. Но важно правило:

  • внутри async-эндпоинта нельзя вызывать блокирующие операции (долгие синхронные запросы к БД/сети), иначе вы “заморозите” event loop
  • Если вы используете async, нужно подбирать совместимые компоненты:

  • async HTTP-клиенты
  • async драйверы БД
  • async режим ORM
  • Про async в SQLAlchemy: Asynchronous I/O — SQLAlchemy

    Async в Django

    Django поддерживает ASGI и async-вьюхи, но реальная выгода зависит от того, какие компоненты вокруг (ORM, middleware, внешние вызовы). Важно читать актуальные ограничения и рекомендации.

    Документация: Asynchronous support — Django

    Как выбрать: sync или async

    Практичное правило:

  • если сервис простой и нагрузка умеренная, синхронный стек часто дешевле по сложности
  • если у вас много одновременных I/O (внешние API, долгие запросы, стриминг), async может дать выигрыш
  • В любом случае “async ради async” — плохая цель. Важнее архитектура, тесты, безопасность и правильная работа с БД.

    Как эти темы складываются в систему

    Если собрать всё вместе, получится практичная “карта зрелости” сервиса:

  • тестирование защищает от регрессий и ускоряет изменения
  • безопасность защищает данные и пользователей
  • кеширование снижает нагрузку на БД и ускоряет ответы
  • очередь разгружает HTTP-слой и делает тяжёлые задачи управляемыми
  • асинхронность повышает эффективность при большом числе I/O-операций
  • Главная мысль уровня Middle: вы проектируете не “набор эндпоинтов”, а систему, которая корректно работает под нагрузкой, предсказуемо изменяется и выдерживает сбои.

    5. Доставка в прод: Docker, CI/CD, мониторинг, архитектура и подготовка к собеседованиям

    Доставка в прод: Docker, CI/CD, мониторинг, архитектура и подготовка к собеседованиям

    Вы уже прошли фундамент: Python Core, инструменты разработчика, основы HTTP/REST и работу с БД, а также надёжность (тесты, безопасность, кеши, очереди, асинхронность). Следующий шаг до уровня уверенного Middle — уметь не только писать код, но и доставлять его в production так, чтобы сервис:

  • повторяемо собирался и запускался на любой машине
  • автоматически проверялся при каждом изменении
  • корректно обновлялся без ручной “магии”
  • был наблюдаемым: по логам/метрикам/трейсам понятно, что происходит
  • имел понятную архитектуру, которую легко расширять
  • Эта статья закрывает практический контур delivery: Docker, CI/CD, мониторинг и эксплуатационная зрелость, плюс — как это упаковать в сильную подготовку к собеседованиям.

    !Диаграмма показывает путь изменения кода от коммита до продакшена и наблюдаемость

    Что означает “доставка в прод”

    Production — среда, где вашим сервисом пользуются реальные пользователи. “Доставка в прод” обычно включает:

  • сборку и упаковку приложения
  • запуск и обновление приложения на сервере или в кластере
  • настройку окружения (переменные окружения, секреты)
  • миграции базы данных
  • контроль качества (тесты, линтеры) до деплоя
  • наблюдаемость (логи, метрики, алерты)
  • Важная мысль: продакшен — это не только “код”. Это ещё и процессы.

    Docker: единый формат упаковки и запуска

    Docker решает фундаментальную проблему: “у меня локально работает, а на сервере нет”. Он упаковывает приложение вместе с его зависимостями и окружением в образ (image), из которого запускается контейнер (container).

    Термины:

  • image — шаблон (слои файловой системы + метаданные)
  • container — запущенный экземпляр image (процесс + файловая система)
  • registry — хранилище образов (Docker Hub, GitHub Container Registry и т.д.)
  • Документация:

  • Docker documentation
  • Как Docker связан с Python backend

    Docker помогает стандартизировать:

  • версию Python
  • системные зависимости (например, libpq для PostgreSQL-драйверов)
  • установку Python-зависимостей
  • команду запуска ASGI/WSGI сервера
  • Итого: один и тот же образ запускается одинаково в dev/stage/prod.

    Базовый Dockerfile для FastAPI

    Ниже пример минимального, но практичного Dockerfile для FastAPI + Uvicorn. Он:

  • использует официальный образ Python
  • ставит зависимости
  • копирует код
  • запускает приложение
  • Что здесь важно:

  • PYTHONUNBUFFERED=1 делает логи “живыми” (важно для контейнерных логов).
  • --no-cache-dir уменьшает размер образа.
  • --host 0.0.0.0 нужен, чтобы контейнер слушал внешний интерфейс.
  • Документация FastAPI по деплою:

  • Deployment Concepts — FastAPI
  • Улучшения, которые быстро поднимают зрелость

    #### Запуск не от root

    Базовая практика безопасности: запускать приложение от непривилегированного пользователя.

    #### Multi-stage сборка (когда нужны системные зависимости)

    Multi-stage помогает отделить “сборочную” среду от “рантайма”, уменьшая итоговый образ. Это особенно полезно, если вы собираете зависимости с компиляцией.

    Документация:

  • Multi-stage builds — Docker
  • Docker Compose для локальной разработки

    Для backend-проекта часто нужны PostgreSQL и Redis. Compose позволяет поднимать весь стек одной командой.

    Команды:

    Документация:

  • Docker Compose documentation
  • Конфигурация и секреты в контейнерном мире

    Правило: конфигурация должна приходить снаружи, а не быть “зашита” в образ.

    Практика:

  • настройки через переменные окружения
  • секреты не хранятся в Git
  • в CI/CD секреты хранятся в secret storage платформы (GitHub Actions Secrets, GitLab CI Variables и т.д.)
  • Это продолжение темы про переменные окружения и безопасность из предыдущих блоков.

    CI/CD: автоматическая проверка и доставка

    CI/CD — это практика, при которой изменения:

  • автоматически проверяются (CI: Continuous Integration)
  • автоматически доставляются в окружения (CD: Continuous Delivery/Deployment)
  • Минимальная цель: при каждом pull request вы получаете воспроизводимый результат “тесты прошли / не прошли”, а при merge в main у вас есть повторяемая сборка артефакта (Docker-образа).

    Типичный пайплайн для Python backend

    Стадии (примерная структура):

  • lint: форматирование и линтинг (Ruff)
  • typecheck: проверка типов (mypy или pyright)
  • test: unit и интеграционные тесты (pytest)
  • build: сборка Docker image
  • push: публикация image в registry
  • deploy: деплой в среду (stage/prod)
  • Пример CI на GitHub Actions

    Документация:

  • GitHub Actions documentation
  • Ниже пример workflow, который устанавливает зависимости и запускает Ruff и pytest.

    Если в проекте есть Docker-сборка, следующим шагом будет docker build и публикация в registry.

    Ключевые практики CI/CD уровня Middle

  • быстрый фидбек: lint и unit-тесты должны отрабатывать быстро
  • воспроизводимость: окружение в CI максимально похоже на prod (версия Python, системные зависимости)
  • “ничего руками”: деплой должен быть скриптуемым и повторяемым
  • миграции БД выполняются управляемо (отдельный шаг, контроль ошибок)
  • Деплой: сервер, reverse proxy и процесс запуска

    На практике есть несколько распространённых вариантов деплоя Python backend.

    Docker на одном сервере

    Подходит для небольших проектов и старта.

    Типовая схема:

  • сервер (Linux)
  • Docker + Docker Compose
  • reverse proxy (часто Nginx), который принимает HTTPS и проксирует в контейнер
  • Документация Nginx:

  • Nginx documentation
  • Kubernetes и оркестрация

    Kubernetes решает задачи масштабирования и управления множеством сервисов, но добавляет сложность. На уровне “с нуля до Middle” важно понимать концепты:

  • deployment управляет репликами приложения
  • service даёт стабильную точку доступа
  • ingress принимает внешний трафик
  • readiness/liveness probes управляют здоровьем
  • Документация:

  • Kubernetes documentation
  • Мониторинг и наблюдаемость: логи, метрики, трейсы

    Если сервис в продакшене, вопрос не “будут ли проблемы”, а “как быстро вы их заметите и локализуете”. Наблюдаемость обычно строится на трёх сигналах:

  • логи: события и ошибки
  • метрики: численные показатели во времени
  • трейсы: путь запроса через компоненты системы
  • Эта тройка часто называется observability.

    !Иллюстрация трёх сигналов наблюдаемости и куда они отправляются

    Логи

    Правила продакшен-логов:

  • используйте logging, не print
  • логируйте ошибки со stack trace
  • логи должны быть структурированными или хотя бы стабильными по формату
  • чувствительные данные (пароли, токены, номера карт) не логируются
  • Документация:

  • logging — Python documentation
  • Метрики и алертинг

    Метрики отвечают на вопросы:

  • сколько запросов в секунду
  • сколько ошибок и какого типа
  • какова задержка (latency)
  • сколько времени занимают запросы к БД
  • Популярный стек:

  • Prometheus для сбора метрик: Prometheus documentation
  • Grafana для визуализации: Grafana documentation
  • Практичные продуктовые метрики зависят от домена, но технически почти всегда нужны:

  • доля ответов 5xx
  • p95/p99 latency (время ответа на хвосте)
  • нагрузка на БД (пулы соединений, долгие запросы)
  • Трейсинг

    Трейсы особенно полезны в микросервисах или когда ваш API делает несколько внешних вызовов.

    Стандарт де-факто — OpenTelemetry:

  • OpenTelemetry documentation
  • Error tracking

    Отдельная категория — сбор исключений и контекста ошибок.

    Популярное решение:

  • Sentry: Sentry documentation
  • Health checks

    Health checks нужны, чтобы инфраструктура понимала: приложение живо и готово принимать трафик.

    Практика:

  • GET /health или GET /ready
  • “жив” не равно “готов”: readiness может проверять доступность БД/кеша
  • В FastAPI обычно делают простой эндпоинт, а более глубокие проверки добавляют аккуратно, чтобы не сделать healthcheck “слишком тяжёлым”.

    Архитектура приложения: как писать так, чтобы проект рос

    Фреймворк решает HTTP-слой, но архитектура решает, насколько легко добавлять функциональность и не ломать старое.

    Принцип разделения слоёв

    Минимальная полезная структура слоёв:

  • API слой: роуты, схемы входа/выхода, HTTP-статусы
  • сервисный слой: бизнес-правила (use cases)
  • доступ к данным: репозитории, ORM/SQL, транзакции
  • инфраструктура: внешние клиенты, кеш, очередь, настройки
  • Идея: бизнес-логика не должна “жить” внутри роутов или моделей ORM.

    Инверсия зависимостей простыми словами

    Профессиональная практика: бизнес-логика зависит от абстракций, а конкретные реализации (PostgreSQL, Redis, HTTP-клиент) подключаются снаружи.

    Это облегчает:

  • тестирование (можно подменять зависимости)
  • замену технологий
  • изоляцию сложных частей
  • 12-factor как чеклист зрелого сервиса

    12-factor app — набор принципов, которые помогают делать сервисы удобными в эксплуатации: конфигурация через окружение, логи как поток событий, отделение сборки от запуска и т.д.

    Источник:

  • The Twelve-Factor App
  • Операционная готовность: что обычно забывают

    Перед реальным продом полезно иметь короткий чеклист.

    Релиз и откат

  • есть версионирование (тег образа, git sha)
  • деплой не перетирает “последнюю рабочую версию” без возможности отката
  • понятен сценарий rollback
  • Миграции базы данных

  • миграции запускаются управляемо
  • изменения схемы совместимы с постепенным выкатыванием (если сервисов несколько)
  • критичные миграции протестированы на копии данных или на staging
  • Таймауты и ретраи

  • HTTP-клиенты ходят во внешние сервисы с таймаутами
  • ретраи применяются только там, где операция идемпотентна или защищена ключом идемпотентности
  • Подготовка к собеседованиям: что спрашивают у Python backend

    Собеседование на Junior+/Middle проверяет не “знание функций Python”, а умение строить и поддерживать сервис.

    Темы, которые стоит уметь объяснить уверенно

  • Python: модель памяти, изменяемость, исключения, контекстные менеджеры, генераторы, типизация
  • HTTP и REST: методы, статусы, идемпотентность, пагинация, версионирование
  • БД: индексы, транзакции, уровни изоляции на уровне идеи, JOIN, N+1 проблема в ORM
  • Тестирование: unit vs integration, фикстуры, моки, границы системы
  • Безопасность: хранение паролей, SQL-инъекции, авторизация, работа с секретами
  • Docker: что такое image/container, как устроен Dockerfile, переменные окружения
  • CI/CD: что проверять в CI, как сделать пайплайн быстрым и полезным
  • Наблюдаемость: логи/метрики/трейсы, что алертить
  • Как усилить резюме и портфолио

    Хороший учебный проект для middle-уровня обычно включает:

  • API на FastAPI или Django REST Framework
  • PostgreSQL + миграции
  • кеш (например, Redis) или очередь (например, Celery)
  • тесты (pytest) и CI
  • Dockerfile и docker-compose
  • минимальный мониторинг (хотя бы корректные логи, healthcheck, базовые метрики)
  • Главное: чтобы проект был собираемым одной командой и имел понятный README.

    Итог

    Теперь у вас есть целостная картина “как довести сервис до продакшена”:

  • Docker даёт единый формат сборки и запуска
  • CI/CD превращает проверку и релиз в повторяемый процесс
  • мониторинг делает сервис наблюдаемым и управляемым в эксплуатации
  • архитектурные принципы помогают проекту расти без постоянных переписываний
  • понимание этих тем напрямую конвертируется в уверенность на собеседованиях
  • На уровне Middle ценится способность видеть систему целиком: от HTTP-контракта и транзакций в БД до пайплайна доставки и алертов по ошибкам.