Тесты видят исходники, а установленный пакет сломан: зачем нужен src layout
Из корня репозитория import ledger работает, тесты проходят. После установки wheel в другой каталог пакет не находится или теряет подмодуль. В рабочем дереве интерпретатор мог импортировать исходники напрямую, минуя результат сборки. Проверяли один набор файлов, а пользователю доставили другой.
Расположение src/ledger отделяет импортируемый пакет от корня проекта. Чтобы использовать его в окружении разработки, пакет нужно установить, например через python -m pip install -e . . Текущий каталог всё ещё участвует в поиске модулей, но каталога ledger непосредственно в корне уже нет. Это уменьшает вероятность незаметной подмены установленной версии исходниками.
Пакет отдельно от корня
Создайте pyproject.toml и положите функцию в src/ledger/__init__.py. Ниже показаны оба файла. Минимальный пример использует setuptools как backend сборки; диапазон версий backend задайте согласно принятой в проекте политике. Важно, чтобы настройка обнаружения пакетов соответствовала выбранной структуре.
# pyproject.toml
[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"
[project]
name = "ledger-example"
version = "0.1.0"
requires-python = ">=3.12"
[tool.setuptools.packages.find]
where = ["src"]
# src/ledger/__init__.py
def total(values: list[int]) -> int:
return sum(values)
Проверка установленного wheel
Для разработки выполните python -m pip install -e . и проверьте import ledger. Для проверки поставки установите build командой python -m pip install build, затем выполните python -m build. Создайте чистое окружение и установите туда конкретный wheel из dist. Проверку импорта запустите из временного каталога вне репозитория: python -c "import ledger; print(ledger.total([2, 3]))". Ожидаемый ответ — 5.
Editable-установка удобна, но не заменяет проверку wheel. Backend может предоставлять доступ к файлам рабочего дерева, которые не попали в обычный дистрибутив. Поэтому импорт после editable install и импорт после установки wheel отвечают на разные вопросы. Первый помогает разрабатывать, второй проверяет то, что получит потребитель.
Посмотрите и на путь ledger.__file__. Он должен соответствовать выбранному окружению и форме установки. Если команда использует другой python, можно бесконечно переустанавливать пакет в правильное, но не участвующее в запуске окружение. Связка python -m pip делает используемый интерпретатор явным и уменьшает такую путаницу.
Отдельно проверьте не только верхний импорт, но и публичные подмодули, необходимые данные и точку входа. src layout не добавляет ресурсы в wheel автоматически. Он помогает обнаружить неправильное предположение о путях раньше. Полезный критерий готовности прост: чистое окружение запускает публичный сценарий без рабочего дерева и без ручного изменения PYTHONPATH.
Следующий шаг — перенести этот приём из отдельного файла в поддерживаемое приложение. В курсе «Python для продвинутых: ООП, типизация и тестирование» структура пакетов, объектная модель, mypy и pytest соединяются в типизированном трекере задач с хранением данных и логированием. Можно отработать связь между интерфейсом, реализацией и регрессионным тестом, а затем применить её к своему проекту.
Посмотреть программу и практику курса.
Документация: официальный источник по теме.
Другие задачи по теме: Типы, тесты и поведение программы.
Продолжить на практике
- Python для продвинутых: ООП, типизация и тестирование ↗
Практический курс-мост от базового Python к разработке поддерживаемых приложений. Вы разберётесь со структурой пакетов, объектной моделью, современной типизацией и автоматическими тестами, а затем соедините эти инструменты в небольшом приложении с хранением данных и логированием.
