Чтобы настроить обнаружение пакетов для проекта Python с использованием структуры src на macOS, укажите setuptools на каталог src в файле pyproject.toml, а затем задайте фильтры имен пакетов, только если вам нужно контролировать состав включаемых в дистрибутив пакетов. В стандартных проектах setuptools часто определяет структуру автоматически; явные параметры обнаружения полезны, когда требуется предсказуемое включение или исключение пакетов. Эти инструкции применимы именно к setuptools, а не ко всем бэкендам сборки Python.

Проверка структуры проекта и бэкенда сборки

В программе «Терминал» перейдите в корневой каталог проекта — папку, содержащую pyproject.toml, — и проверьте файлы с помощью оболочки zsh (используется в macOS по умолчанию) или bash, если у вас настроена она:

cd '/path/to/project'
find src -maxdepth 3 -type f -print

Замените путь в кавычках на фактическое расположение проекта. Одинарные кавычки предотвращают интерпретацию пробелов и метасимволов командной строки в пути. Типичный пакет может располагаться по пути src/my_package/__init__.py с подпакетами во вложенных каталогах. Имя импорта — my_package; каталог src является лишь контейнером и не входит в это имя.

Убедитесь, что в файле pyproject.toml в секции [build-system] выбран setuptools, например с помощью requires = ["setuptools>=61"] и build-backend = "setuptools.build_meta". В документации setuptools описано автоматическое обнаружение для распространенных структур, включая src, когда списки пакетов и модулей не заданы явно. У других бэкендов используются собственные настройки, поэтому не переносите параметры setuptools в таблицу конфигурации другого бэкенда. Setuptools: Configuring setuptools using pyproject.toml files

Настройка явного обнаружения в pyproject.toml

Если вы хотите, чтобы поиск пакетов производился непосредственно в src, добавьте следующую конфигурацию setuptools в существующий файл:

[tool.setuptools.packages.find]
where = ["src"]

Это указывает setuptools, где искать пакеты. Это не меняет имя проекта или имя пакета для импорта. Если у вас уже есть таблица [tool.setuptools.packages.find], отредактируйте ее, а не добавляйте вторую. Файлы TOML не могут содержать дублирующиеся определения одной и той же таблицы.

Чтобы ограничить обнаружение одним пакетом и его подпакетами, добавьте шаблон include, соответствующий полному имени пакета через точку:

[tool.setuptools.packages.find]
where = ["src"]
include = ["my_package*"]

Замените my_package на фактическое имя пакета для импорта. Символ * позволяет шаблону соответствовать подпакетам, таким как my_package.tools; сопоставление шаблонов выполняется по полным именам пакетов. Вы также можете исключать определенные пакеты, например: exclude = ["my_package.tests*"]. Параметры шаблонов include и exclude, а также where, описаны в руководстве setuptools по обнаружению пакетов.

Выбор способа обработки пакетов пространств имен (namespace packages)

По умолчанию механизм обнаружения setuptools в pyproject.toml сканирует неявные пакеты пространств имен: каталоги могут считаться пакетами, даже если они не содержат __init__.py. Сохраните это поведение по умолчанию, если в вашем проекте намеренно используются пакеты пространств имен PEP 420. Если каждый пакет должен содержать __init__.py, вы можете отключить сканирование пространств имен:

[tool.setuptools.packages.find]
where = ["src"]
namespaces = false

При таком значении каталоги без __init__.py не будут определяться как пакеты. Таким образом, отсутствие пакета в собранном дистрибутиве может объясняться местом поиска, шаблоном include или exclude, либо параметром пространств имен. В руководстве по упаковке рассматривается это поведение и показано, как можно ограничить обнаружение определенными пакетами пространств имен. Python Packaging User Guide: Packaging namespace packages

В каких случаях достаточно автоматического обнаружения

Для простого проекта со структурой src/my_package таблица обнаружения может вовсе не потребоваться. Setuptools способен распознавать стандартные структуры каталогов, если packages и py-modules не указаны. Добавляйте явную конфигурацию тогда, когда требуется сузить выборку пакетов, настроить нестандартное дерево каталогов или однозначно определить каталог с исходным кодом. Избегайте жестко заданных вручную списков пакетов, если только вы не собираетесь поддерживать их при каждом изменении структуры пакета; при использовании явных списков легко упустить вновь добавленные подпакеты.

Структура src также означает, что запуск Python из корня репозитория не помещает пакет в путь импорта автоматически. Это нормальное поведение: в документации setuptools отмечается, что для использования пакета из каталога исходного кода таким образом требуется редактируемая установка (editable install). Конфигурация обнаружения определяет, что будет включено в дистрибутив; она не заменяет установку проекта в окружение Python, используемое для разработки. Setuptools: Package Discovery and Namespace Packages

Источники