Python Pro: От учебных скриптов к реальным продуктам

Практический курс для разработчиков с базовыми знаниями, желающих освоить полный цикл создания ПО. Вы пройдете путь от настройки окружения до деплоя, создав портфолио из CLI-утилиты и веб-сервиса с использованием современных инструментов (Docker, Pytest, Poetry).

1. Экосистема профи: Git, виртуальные окружения и стандарты кода

Экосистема профи: Git, виртуальные окружения и стандарты кода

Добро пожаловать в профессиональную лигу. Если раньше ваш код жил в одном файле main.py на рабочем столе, а библиотеки устанавливались глобально командой pip install, то сегодня мы меняем правила игры.

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

Почему «работает на моем компьютере» — это не аргумент

Представьте, что вы строите дом. Любительский подход — это прийти на стройку с одним молотком и кучей разнородных материалов, сваленных в кучу. Профессиональный подход — это организованный склад, четкие чертежи и стандартизированные инструменты.

В Python «склад» и «инструменты» — это виртуальные окружения, управление зависимостями и контроль версий. Без них любой проект сложнее «Hello World» обречен на так называемый «Dependency Hell» (Ад зависимостей).

!Сравнение глобальной установки пакетов и изолированных виртуальных окружений

Виртуальные окружения: Изоляция прежде всего

Главное правило Python-разработчика: никогда не устанавливайте пакеты в системный интерпретатор.

Почему? Представьте, что Проекту А нужен Django 3.0, а Проекту Б — Django 4.0. Если вы ставите их глобально, один из проектов перестанет работать. Виртуальное окружение (venv) создает изолированную папку с собственной копией интерпретатора Python и менеджера пакетов pip.

Классический подход: venv

Это встроенный инструмент, который есть в Python по умолчанию. Создание окружения выглядит так:

После создания его нужно активировать:

* Windows: venv\Scripts\activate * macOS / Linux: source venv/bin/activate

Когда окружение активировано, в терминале появится префикс (venv). Теперь все, что вы установите через pip install, попадет только в эту папку.

Современный стандарт: Poetry

Хотя venv и requirements.txt (список зависимостей) являются классикой, индустрия движется к более мощным инструментам. Мы в курсе будем использовать Poetry.

Poetry решает сразу три задачи:

  • Управляет виртуальным окружением (создает его сама).
  • Управляет зависимостями (разрешает конфликты версий).
  • Помогает упаковывать проект для публикации.
  • Установка Poetry (выполняется один раз глобально):

    Инициализация нового проекта:

    Это создаст правильную структуру папок и файл pyproject.toml — паспорт вашего проекта.

    Управление зависимостями: pyproject.toml

    Файл requirements.txt — это просто список. Файл pyproject.toml — это декларация. В нем описывается не только то, какие библиотеки нужны, но и какие версии совместимы, а также настройки инструментов разработки.

    Пример добавления библиотеки через Poetry:

    Poetry автоматически:

  • Найдем подходящую версию requests.
  • Скачает её и все её зависимости.
  • Запишет информацию в pyproject.toml и poetry.lock.
  • Файл poetry.lock критически важен. Он «замораживает» конкретные версии всех установленных пакетов. Это гарантирует, что если ваш коллега скачает проект и запустит poetry install, у него будет бит-в-бит то же самое окружение, что и у вас.

    Git: Ваша машина времени

    Git — это не просто способ сохранить код. Это история развития вашего продукта. В профессиональной разработке мы следуем нескольким правилам:

    1. Правильный .gitignore

    Не все файлы должны попадать в репозиторий. Мусор, временные файлы, настройки IDE и само виртуальное окружение должны быть проигнорированы.

    Типичный .gitignore для Python:

    Обратите внимание на .env. В этом файле хранятся секреты (пароли, API-ключи). Никогда не отправляйте .env в Git. Для примера создают файл .env.example с пустыми значениями.

    2. Атомарные коммиты

    Плохой коммит: > "Исправил баг, добавил новую фичу и переписал половину проекта"

    Хороший коммит: > "Fix: исправление ошибки валидации email"

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

    Чистота кода: Линтеры и Форматтеры

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

    Flake8: Полиция нравов

    flake8 проверяет ваш код на соответствие стандарту PEP 8 и ищет логические ошибки (например, импортированный, но неиспользуемый модуль).

    Установка:

    Запуск:

    Black: Бескомпромиссный форматтер

    Споры о том, ставить пробелы вокруг знака = или нет, отнимают время. Black решает эти споры раз и навсегда. Он просто берет ваш код и переписывает его в едином стиле.

    Установка:

    Запуск:

    isort: Порядок в импортах

    Импорты должны быть отсортированы: сначала стандартные библиотеки, потом сторонние, потом ваши собственные. isort делает это автоматически.

    Структура профессионального проекта

    Забудьте о свалке файлов в корне папки. Стандартная структура выглядит так:

    Папка src (source) используется для того, чтобы избежать путаницы при импортах и четко отделить код приложения от конфигурационных файлов.

    Практическое задание: Настройка окружения

    Прежде чем мы начнем писать код первого проекта (CLI-утилиты), подготовьте свою рабочую станцию:

  • Установите Git и настройте user.name и user.email.
  • Установите Python 3.10+.
  • Установите Poetry.
  • Создайте тестовый проект командой poetry new python-pro-setup.
  • Добавьте в него flake8 и black как dev-зависимости.
  • Создайте репозиторий на GitHub и отправьте туда первый коммит (не забудьте про .gitignore!).
  • Теперь вы готовы к настоящей разработке. В следующем модуле мы напишем нашу первую профессиональную CLI-утилиту, используя этот фундамент.

    2. Проект 1: Разработка надежной CLI-утилиты и работа с файлами

    Проект 1: Разработка надежной CLI-утилиты и работа с файлами

    В предыдущем модуле мы подготовили профессиональную среду разработки: настроили Git, Poetry и линтеры. Теперь пришло время написать код, который не стыдно показать коллегам.

    Мы не будем писать очередной скрипт «Hello World». Мы создадим FileSorter — полноценную CLI-утилиту (Command Line Interface) для автоматической сортировки файлов в директории по их расширениям. Это классическая задача автоматизации, на примере которой мы разберем отличия любительского скрипта от надежного инженерного решения.

    Отличие скрипта от инструмента

    Любитель пишет скрипт, который работает «здесь и сейчас» на конкретной машине. Профессионал создает инструмент, который:

  • Предсказуем: Он не удалит ваши файлы случайно.
  • Универсален: Работает на Windows, Linux и macOS без переписывания путей.
  • Информативен: Сообщает, что делает, и объясняет ошибки, а не просто падает с Traceback.
  • !Схема архитектуры CLI-приложения: от ввода команды до результата

    Современная работа с файловой системой: pathlib

    Долгое время стандартом в Python был модуль os.path. Вы наверняка видели код вроде os.path.join(dir, file). В современном Python (3.4+) мы используем модуль pathlib. Это объектно-ориентированный подход к путям.

    Почему pathlib — это выбор профи:

    * Кроссплатформенность: Windows использует обратные слеши \, а Unix — прямые /. pathlib обрабатывает это автоматически. * Читаемость: Вместо вложенных функций вы используете методы объектов.

    Сравните:

    Обратите внимание на оператор /. В pathlib он перегружен и работает как интуитивное объединение частей пути.

    Проектирование интерфейса: argparse

    Профессиональная утилита не должна спрашивать данные через input(). Интерактивный ввод блокирует автоматизацию. Если вы хотите запустить свой сортировщик по расписанию ночью, некому будет вводить путь к папке.

    Мы будем использовать аргументы командной строки. Стандартная библиотека Python предлагает мощный модуль argparse.

    Наша утилита должна принимать:

  • Путь к папке, которую нужно разобрать (обязательный аргумент).
  • Флаг --dry-run (опционально) — режим «сухого прогона», когда программа только пишет, что сделала бы, но не трогает файлы реально. Это золотой стандарт безопасности.
  • Каркас приложения

    Создайте файл src/filesorter/main.py (структура из прошлого урока) и начнем с парсера:

    Теперь, если вы запустите программу с флагом --help, Python автоматически сгенерирует документацию. Это и есть профессиональный подход: самодокументируемый код.

    Логирование вместо print

    Использование print() для отладки или сообщений о статусе — плохая практика в продакшене. print выводит все в стандартный поток вывода (stdout). Но что, если пользователь хочет перенаправить вывод ошибок в файл?

    Используйте модуль logging. Он позволяет разделять сообщения по уровням важности: * DEBUG: подробная информация для разработчика. * INFO: стандартные сообщения о ходе работы. * WARNING: что-то пошло не так, но работа продолжается. * ERROR: ошибка, операция не выполнена.

    Настроим простой логгер:

    Реализация логики сортировки

    Теперь напишем «сердце» нашей программы. Нам нужно:

  • Проверить, существует ли папка.
  • Пройтись по всем файлам.
  • Определить расширение файла.
  • Создать целевую папку (например, Images для .jpg).
  • Переместить файл.
  • Безопасное перемещение

    Главный страх при работе с файлами — перезапись. Если у вас есть photo.jpg в корне и photo.jpg в папке Images, простое перемещение может уничтожить один из них.

    Реализуем функцию с защитой:

    Обратите внимание на shutil. Модуль pathlib умеет перемещать файлы через Path.rename(), но shutil.move надежнее работает при перемещении между разными физическими дисками.

    Собираем все вместе

    Объединим части в функцию main. Мы также добавим словарь для маппинга расширений к названиям папок.

    Почему этот код лучше, чем у 90% новичков

  • Обработка исключений: Мы обернули перемещение в try...except. Если один файл заблокирован системой, программа не упадет, а запишет ошибку в лог и продолжит работу со следующими файлами.
  • Dry Run: Вы можете запустить python main.py ./my_folder --dry-run и безопасно посмотреть, что произойдет.
  • Resolve: Метод .resolve() превращает относительный путь (например, .) в абсолютный. Это важно для логирования, чтобы вы точно знали, где происходили изменения.
  • Type Hinting: Мы явно указываем типы (file: Path), что помогает IDE подсказывать методы и предотвращает глупые ошибки.
  • Практическое задание

    Ваша задача — доработать этот проект до состояния готового продукта.

  • Скопируйте код в свой проект, созданный через Poetry.
  • Добавьте в EXTENSION_MAP категории для музыки (.mp3, .wav) и кода (.py, .js, .html).
  • Реализуйте аргумент --recursive (или -r), который заставит утилиту проходить не только по указанной папке, но и по всем вложенным подпапкам. Подсказка: изучите метод Path.rglob().
  • Запустите линтеры (flake8, black), чтобы привести код к идеальному стилю.
  • В следующем модуле мы научимся писать автоматические тесты для этой утилиты, чтобы гарантировать, что она никогда не удалит ваши важные документы.

    3. Проект 2: Создание REST API сервиса на FastAPI

    Проект 2: Создание REST API сервиса на FastAPI

    В предыдущем модуле мы научились создавать надежные инструменты для локального использования. Но современный мир разработки не ограничивается одним компьютером. Сегодня программы общаются друг с другом через сеть. Мобильные приложения, веб-сайты и микросервисы — все они обмениваются данными через API.

    В этом модуле мы перейдем от скриптов к сервисам. Мы создадим TaskTracker API — веб-сервис для управления задачами. Это будет не просто учебный пример, а фундамент для полноценного бэкенда, построенный на самом современном фреймворке Python — FastAPI.

    Что такое REST API и почему FastAPI?

    Если CLI-утилита принимает аргументы командной строки, то веб-сервис принимает HTTP-запросы.

    REST (Representational State Transfer) — это архитектурный стиль взаимодействия компонентов распределенного приложения в сети. Упрощенно, это набор правил того, как программист должен организовать URL-адреса и методы HTTP, чтобы всем было понятно, как пользоваться его сервисом.

    !Схема цикла запрос-ответ в REST API архитектуре

    Почему мы выбираем FastAPI, а не Django или Flask?

  • Скорость: Он действительно быстрый (на уровне Go и NodeJS) благодаря асинхронности.
  • Строгая типизация: FastAPI глубоко интегрирован с подсказками типов (Type Hints), что снижает количество багов.
  • Автоматическая документация: Вы пишете код, а FastAPI сам генерирует интерактивную документацию Swagger UI.
  • Настройка окружения

    Продолжаем использовать Poetry. Создайте новый проект или используйте существующий репозиторий.

    Нам понадобятся две главные библиотеки: * fastapi: сам веб-фреймворк. * uvicorn: высокопроизводительный ASGI-сервер, который будет запускать наше приложение.

    Контракты данных: Pydantic

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

    FastAPI использует библиотеку Pydantic. Мы описываем структуру данных как класс, а библиотека гарантирует, что данные соответствуют этому описанию.

    Создайте файл src/main.py:

    Здесь мы объявили, что каждая задача обязана иметь заголовок (title), может иметь описание и статус выполнения. Если пользователь пришлет задачу без заголовка, FastAPI автоматически вернет ошибку, даже не запуская нашу логику.

    Реализация эндпоинтов (Endpoints)

    Эндпоинт — это точка входа в API (конкретный URL и метод). Поскольку мы пока не подключили базу данных, будем хранить задачи в оперативной памяти.

    Добавьте этот код в src/main.py:

    Разберем магию декораторов: * @app.get и @app.post: указывают HTTP-метод. * response_model: говорит FastAPI, в каком формате отдавать ответ. Это фильтрует лишние данные. * async def: позволяет серверу обрабатывать тысячи запросов одновременно, не блокируясь на ожидании (например, пока база данных ответит).

    Обработка ошибок и параметры пути

    Что если клиент запросит задачу, которой нет? Мы должны вернуть правильный HTTP-код ошибки (404 Not Found).

    Обратите внимание на {task_id} в пути и аргумент task_id: int в функции. FastAPI автоматически извлечет число из URL и передаст его в функцию. Если пользователь напишет /tasks/hello, FastAPI вернет ошибку валидации, так как "hello" — это не int.

    Запуск сервера

    Веб-сервис — это процесс, который должен работать постоянно. Для запуска используем Uvicorn.

    В терминале (находясь в корне проекта):

    * src.main:app: путь к объекту приложения (файл src/main.py, переменная app). * --reload: режим разработчика. Сервер будет перезагружаться автоматически при изменении кода.

    Если вы увидите надпись Application startup complete, значит, ваш сервер запущен на http://127.0.0.1:8000.

    Интерактивная документация

    Теперь самое интересное. Откройте в браузере адрес:

    http://127.0.0.1:8000/docs

    Вы увидите Swagger UI. Это автоматически сгенерированная веб-страница, где перечислены все ваши эндпоинты. Вы можете нажать кнопку "Try it out", заполнить JSON и отправить реальный запрос к вашему API прямо из браузера.

    Это профессиональный стандарт. Фронтенд-разработчики и тестировщики будут любить вас за такую документацию.

    Структура проекта: Router

    Хранить весь код в main.py — плохая практика, допустимая только для прототипов. В реальном проекте мы разделяем логику.

    Профессиональная структура FastAPI проекта:

    В src/routers/tasks.py мы используем APIRouter:

    А в main.py просто подключаем его:

    Практическое задание

    Ваша задача — превратить этот прототип в полноценный API для управления списком дел.

  • Реализуйте метод DELETE для удаления задачи по ID.
  • Реализуйте метод PUT для обновления задачи (например, чтобы отметить её как выполненную).
  • Добавьте валидацию: длина заголовка задачи не должна превышать 50 символов (изучите pydantic.Field).
  • Разнесите код по файлам: модели отдельно, роутеры отдельно, main.py отдельно.
  • В следующем модуле мы подключим к нашему API настоящую базу данных, чтобы задачи не исчезали после перезагрузки сервера.

    4. Культура разработки: тестирование с Pytest и обработка ошибок

    Культура разработки: тестирование с Pytest и обработка ошибок

    Вы написали код, запустили его, и он сработал. Отлично! Но можете ли вы гарантировать, что он будет работать завтра? А если вы измените одну строчку в другой части проекта, не сломается ли текущий функционал?

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

    Страх изменений и регрессия

    Представьте ситуацию: вы добавляете новую функцию в наш FileSorter (из Проекта 1) — например, распаковку архивов. Вы дописали код, проверили — архивы распаковываются. Вы довольны.

    Но через неделю выясняется, что сортировка картинок перестала работать. Оказывается, ваш новый код случайно изменил логику определения путей. Это называется регрессия — появление ошибок в уже протестированном функционале после внесения изменений.

    Ручное тестирование («прокликивание» или запуск скрипта руками) с ростом проекта становится невозможным. На помощь приходят автоматические тесты.

    !Цикл разработки через тестирование (TDD)

    Почему Pytest?

    В Python есть встроенный модуль unittest, вдохновленный Java JUnit. Он надежный, но громоздкий. Стандартом современной разработки является Pytest.

    Его преимущества:

  • Лаконичность: Не нужно создавать классы-наследники. Обычные функции — это уже тесты.
  • Магия assert: Не нужно помнить методы вроде self.assertEqual или self.assertTrue. Вы просто пишете assert x == y.
  • Фикстуры (Fixtures): Мощный механизм подготовки данных.
  • Установка

    Добавим библиотеку в наш проект через Poetry (как dev-зависимость, так как в продакшене тесты не нужны):

    Пишем первый тест

    Вспомним наш проект FileSorter. У нас была логика определения папки по расширению файла. Давайте вынесем её в отдельную функцию (если вы этого еще не сделали) и протестируем.

    Файл src/filesorter/logic.py:

    Теперь создадим файл tests/test_logic.py. Pytest автоматически ищет файлы, начинающиеся на test_.

    Запустите тесты командой:

    Вы увидите зеленый прогресс-бар. Если вы намеренно сломаете код (например, измените "Images" на "Pictures"), Pytest покажет детальный отчет: что ожидалось и что было получено.

    Параметризация: DRY в тестах

    Писать отдельную функцию для каждого расширения (test_jpg, test_txt, test_zip) — это нарушение принципа DRY (Don't Repeat Yourself). Pytest позволяет запускать один и тот же тест с разными данными.

    Используем декоратор @pytest.mark.parametrize:

    Теперь Pytest запустит эту функцию 5 раз с разными аргументами. Это позволяет покрыть десятки граничных случаев в несколько строк кода.

    Фикстуры: работа с файловой системой

    Самое сложное в тестировании — это внешние зависимости (файлы, базы данных, сеть). Если ваш тест реально создает файлы на диске, вам нужно потом их удалять. Если тест упадет посередине, мусор останется.

    В Pytest есть встроенная фикстура tmp_path. Она создает временную директорию, которая гарантированно удаляется после теста.

    Протестируем функцию сортировки (предположим, у нас есть функция sort_directory):

    Обратите внимание: мы не писали логику создания и удаления папки. Мы просто добавили аргумент tmp_path, и Pytest сделал всё за нас.

    Культура обработки ошибок

    Тесты гарантируют, что код работает в идеальных условиях. Обработка ошибок гарантирует, что код выживет в реальном мире.

    EAFP против LBYL

    В Python принят принцип EAFP (Easier to Ask for Forgiveness than Permission — Проще попросить прощения, чем разрешения).

    LBYL (Look Before You Leap — классический подход C/Java):

    Проблема: между проверкой if и удалением remove файл может быть удален другой программой. Это состояние гонки.

    EAFP (Pythonic way):

    Этот код надежнее и часто быстрее.

    Создание собственных исключений

    Никогда не используйте raise Exception("Ошибка"). Это слишком общее исключение, которое трудно перехватить точечно. Создавайте свои классы ошибок для проектов.

    Теперь в коде вы можете выбрасывать конкретную ошибку:

    А на уровне выше — ловить именно её:

    Тестирование исключений

    Как проверить, что ваша программа правильно ломается? Если функция должна выбросить ошибку при неверных данных, а она этого не делает — это баг.

    Используйте контекстный менеджер pytest.raises:

    Если move_file выполнится без ошибок (например, вы забыли проверку прав), тест упадет.

    Тестирование API (FastAPI)

    Для нашего второго проекта (TaskTracker) Pytest тоже незаменим. FastAPI предоставляет TestClient, который позволяет делать запросы к вашему API без запуска реального сервера.

    Практическое задание

    Теперь ваша очередь превратить ваш код в профессиональный продукт.

  • Установите pytest в ваш проект.
  • Для FileSorter: напишите параметризованный тест для функции определения расширений. Напишите тест с tmp_path, проверяющий, что файлы реально перемещаются.
  • Для TaskTracker: напишите тесты для эндпоинтов создания и получения задач. Проверьте, что API возвращает 404, если запросить несуществующий ID задачи.
  • Запустите pytest и добейтесь 100% прохождения тестов.
  • В следующем модуле мы упакуем наши протестированные приложения в Docker-контейнеры, чтобы запускать их на любом сервере одной командой.

    5. Финализация: контейнеризация в Docker и подготовка к релизу

    Финализация: контейнеризация в Docker и подготовка к релизу

    Поздравляю! Вы прошли долгий путь. Мы начали с настройки окружения, написали CLI-утилиту для сортировки файлов, создали REST API сервис на FastAPI и покрыли всё это тестами. Ваш код чист, структурирован и работает. На вашем компьютере.

    Но в профессиональной разработке фраза «работает на моей машине» (It works on my machine) — это не оправдание. Серверы в облаке, компьютеры коллег и ноутбук заказчика могут иметь другую операционную систему, другую версию Python или отсутствующие системные библиотеки.

    В этой финальной статье курса мы упакуем наш проект в Docker. Это превратит ваше приложение в универсальный «кирпичик», который гарантированно запустится где угодно.

    Проблема зависимостей и её решение

    Представьте, что вы хотите отправить другу домашний пирог. Вы можете отправить ему рецепт (исходный код). Но у друга может не быть нужной муки, духовка греет слабее, а вместо сахара он по ошибке возьмет соль. Результат будет непредсказуемым.

    Docker позволяет отправить не рецепт, а «мини-кухню» вместе с пирогом, где уже настроена температура, лежат правильные ингредиенты и стоит готовое блюдо.

    Контейнеры против Виртуальных машин

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

    Docker использует контейнеры. Контейнер — это легкая изолированная среда. Она использует ядро основной операционной системы (Linux), но имеет свою файловую систему, свои библиотеки и настройки.

    !Сравнение тяжеловесной архитектуры виртуальных машин и легковесной архитектуры контейнеров

    Пишем Dockerfile

    Чтобы Docker понял, как упаковать ваше приложение, ему нужна инструкция — файл с именем Dockerfile (без расширения). Мы будем упаковывать наш проект TaskTracker (API на FastAPI).

    Создайте файл Dockerfile в корне вашего проекта:

    Разбор ключевых шагов

  • FROM: Любой образ строится на базе другого. python:3.10-slim — это минималистичная версия Linux (Debian) с уже установленным Python.
  • WORKDIR: Это как команда cd. Все дальнейшие команды будут выполняться в папке /app внутри контейнера.
  • COPY: Мы копируем файлы с вашего компьютера (хост) внутрь контейнера. Сначала мы копируем только файлы зависимостей (pyproject.toml, poetry.lock). Почему? Docker кэширует слои. Если вы измените код программы, но не зависимости, Docker пропустит долгий этап установки библиотек.
  • CMD: Это команда, которая выполнится, когда контейнер запустится.
  • Игнорирование лишнего: .dockerignore

    Контейнер должен быть максимально легким. Нет смысла тащить туда папку .git (которая может весить сотни мегабайт), локальное виртуальное окружение или кэш тестов.

    Создайте файл .dockerignore (синтаксис как у .gitignore):

    Обратите внимание на .env. Никогда не упаковывайте секреты внутрь образа! Образ может стать публичным, и ваши пароли утекут. Секреты передаются при запуске контейнера.

    Сборка и запуск

    Теперь превратим наш код в Docker-образ. Откройте терминал в папке проекта.

    Шаг 1: Сборка (Build)

    * -t task-tracker:v1: Мы даем образу имя (tag) task-tracker и версию v1. * .: Точка в конце означает «искать Dockerfile в текущей директории».

    Docker скачает Python, установит Poetry, скачает библиотеки и создаст «слепок» вашего приложения.

    Шаг 2: Запуск (Run)

    * -d (detach): Запустить в фоновом режиме. * -p 8000:8000: Пробросить порт. Левая часть — порт на вашем компьютере, правая — внутри контейнера. Если вы напишете -p 9090:8000, то приложение будет доступно по адресу localhost:9090. * --name: Имя для запущенного контейнера.

    Проверьте работу, открыв http://localhost:8000/docs.

    Оркестрация: Docker Compose

    Запускать команды docker run с кучей флагов неудобно. К тому же, реальные приложения состоят из нескольких сервисов (API + База данных + Кэш).

    Docker Compose — это инструмент для описания и запуска мульти-контейнерных приложений. Конфигурация хранится в файле docker-compose.yml.

    Создайте docker-compose.yml в корне проекта:

    Теперь для запуска всего проекта достаточно одной команды:

    Эта команда соберет образ и запустит контейнер. Если вы добавите в этот файл базу данных (например, PostgreSQL), Docker Compose запустит и её, и даже настроит внутреннюю сеть, чтобы API мог «видеть» базу.

    Лицо проекта: README.md

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

    Файл README.md в корне репозитория — это первое, что видит работодатель или коллега на GitHub. Хороший README должен отвечать на вопросы: «Что это?», «Зачем это?» и «Как это запустить?».

    Структура идеального README

  • Заголовок и бейджы: Название проекта и статус тестов (CI/CD pass/fail).
  • Описание: Кратко (2-3 предложения) о том, какую проблему решает сервис.
  • Технологический стек: Python 3.10, FastAPI, Docker, Poetry, Pytest.
  • Установка и запуск:
  • * Локально через Poetry. * В контейнере через Docker Compose.
  • Примеры использования: Примеры запросов к API (можно скриншоты из Swagger UI).
  • Пример фрагмента README:

    Заключение курса

    Поздравляю! Вы прошли путь от простых скриптов до создания готового к релизу продукта.

    Давайте оглянемся назад и посмотрим, чему вы научились:

  • Организация: Вы больше не сваливаете файлы в кучу, а используете src, tests и виртуальные окружения.
  • Инструментарий: Git, Poetry, Flake8, Black — ваши верные спутники.
  • Архитектура: Вы понимаете разницу между CLI-утилитой и REST API, умеете использовать Pydantic для валидации данных.
  • Качество: Вы пишете тесты на Pytest, чтобы спать спокойно.
  • Доставка: Вы упаковываете приложение в Docker, делая его бессмертным и переносимым.
  • Что дальше?

    Этот курс дал вам фундамент. Дальнейшее развитие зависит от ваших интересов:

    * Backend: Подключите настоящую базу данных (PostgreSQL) через SQLAlchemy и изучите миграции (Alembic). * DevOps: Настройте CI/CD (GitHub Actions), чтобы тесты запускались автоматически при каждом коммите, а Docker-образ сам улетал на сервер. * Frontend: Попробуйте написать простой интерфейс на React или Vue, который будет общаться с вашим API.

    Вы больше не новичок. Вы — разработчик, который умеет создавать продукты. Удачи в новых проектах!