- Вопрос или проблема
- Ответ или решение
- Оценка использования пространств имен в Python-пакетах
- 1. Возможно ли иметь как файл kitchentool.py, так и подкаталог kitchentool/?
- 2. Как правильно организовать структуру, если не следует иметь оба?
- 3. Верны ли мои файлы __init__.py?
- 4. Должен ли cmd быть пространством имен?
- Заключение
Вопрос или проблема
Я начинающий разработчик на Python. Я пытаюсь узнать лучший способ использования пакетов, но сталкиваюсь с проблемами при их сборке и развертывании. Моя настройка:
- Python 3.13+ без необходимости совместимости с версиями до Python 3.9.
- Структура кода “src” (согласно https://packaging.python.org/).
- “pyproject.toml” для конфигурации пакета, потому что это, похоже, новый стандарт.
- “hatchling” для сборки, но я открыт для альтернатив.
Допустим, я работаю в организации “acme”. Есть много небольших проектов на Python только для внутреннего использования, которые я хочу развернуть под пространством имен “acme”.
Допустим также, что один из таких внутренних проектов – “kitchentool”. Вот как я хочу, чтобы он использовался в python-скриптах:
import acme.kitchentool
или
from acme.kitchentool import KitchenTool
Этот проект имеет несколько утилит командной строки, и вот как я хочу, чтобы они вызывались
(я могу убрать подсистему ‘cmd’, если это не является питоничным, но мне нравится разделение исходного кода):
$ python -m acme.kitchentool.cmd.cut --fine
$ python -m acme.kitchentool.cmd.blend --speed 60
$ python -m acme.kitchentool.cmd.roast --temp 350
Вот моя текущая структура исходников, с которой у меня возникают трудности:
acme_kitchentool/ # Корень исходного кода для этого проекта
|-- README.md
|-- pyproject.toml
|-- src/ # Я крайне предпочитаю это 'src' к 'плоской' структуре, по причинам.
| # Нет __init__.py в директории src.
|-- acme/
| # Нет __init__.py в src/acme (пространство имен).
|-- kitchentool.py # Ключевые классы/функции.
|-- kitchentool/ # Эта директория в порядке, если у меня также есть kitchentool.py?
|-- __init__.py # Пустой __init__.py
|-- cmd/ # Подпакет для утилит командной строки
|-- __init__.py # Пустой __init__.py
|-- chop.py # Утилита командной строки
|-- blend.py # Утилита командной строки
|-- roast.py # Утилита командной строки
Вопросы:
-
Можно ли иметь как файл
kitchentool.py
, так и подпапкуkitchentool/
, как показано? -
Если нет, то какой правильный способ добиться желаемого? Должен ли
kitchentool.py
быть__init__.py
в директорииkitchentool/
? -
Правильны ли у меня файлы
__init__.py
? -
Является ли
cmd
технически пространством имен, которое не должно иметь__init__.py
, согласно https://packaging.python.org/en/latest/guides/packaging-namespace-packages/?
Крайне важно, чтобы каждая дистрибуция, использующая пространство имен, не имела init.py или использовала стиль init для pkgutil. Если какая-либо дистрибуция этого не сделает, это приведет к неудаче логики пространства имен, и другие подсистемы не будут доступными для импорта.
Буду рад любым советам. Спасибо!
Ответ или решение
Оценка использования пространств имен в Python-пакетах
Приветствую вас! Отлично, что вы изучаете создание и организацию Python-пакетов. Ваша ситуация с пространствами имен (namespace packages) довольно типична, и давайте рассмотрим основные вопросы и проблемы, которые у вас возникли.
1. Возможно ли иметь как файл kitchentool.py
, так и подкаталог kitchentool/
?
Да, наличие как файла kitchentool.py
, так и подкаталога kitchentool/
в одной и той же структуре пакета допустимо, но не рекомендуемая практика в данной археологии. Если вы хотите иметь обе структуры, это может привести к путанице при импорте и определении, что следует импортировать, особенно если они имеют схожие имена классов или функций. Лучше всего, если вы определите, что именно должно содержаться в вашем проекте, и использовать одно из этих решений:
- Если вы хотите организовать более сложную логику внутри
kitchentool
, рекомендуем использовать только подкаталогkitchentool/
как главный модуль пакета. - Либо оставьте только
kitchentool.py
, если логика достаточно проста.
2. Как правильно организовать структуру, если не следует иметь оба?
Если вы решите пойти по пути структуры с подкаталогом kitchentool/
, вам следует сделать __init__.py
в этом каталоге основным модулем вашего проекта, и переместить содержимое kitchentool.py
в kitchentool/__init__.py
. Это обеспечит ясность для вашего пакета:
src/
|-- acme/
|-- kitchentool/
|-- __init__.py # Ваши классы и функции теперь здесь
|-- cmd/
|-- __init__.py # Как указано ниже, в нем не должно быть содержания
|-- chop.py
|-- blend.py
|-- roast.py
С этим изменением вы сможете использовать код как в примерах import acme.kitchentool
, так и как from acme.kitchentool import KitchenTool
.
3. Верны ли мои файлы __init__.py
?
Ваша текущая структура __init__.py
для подкаталогов в целом правильная. Однако важно, чтобы:
kitchentool/__init__.py
содержал код, который должен быть доступен при импорте вacme.kitchentool
.cmd/__init__.py
может оставаться пустым, если вы не планируете явным образом определять какие-либо функции или классы, которые должны быть доступны на уровнеacme.kitchentool.cmd
.
Если cmd
будет использоваться только как подкаталог для скриптов, вы можете не включать в него __init__.py
, так как это позволит избежать путаницы и будет полностью соответствовать концепции пространств имен.
4. Должен ли cmd
быть пространством имен?
В контексте использования пространства имен cmd
не является необходимым пространством имен, поскольку это всего лишь подкаталог, отвечающий за команды. Вы можете оставить __init__.py
в этом каталоге как пустой файл или даже его убрать, так как он не требует пространственной логики, если все обрабатывается в текущем контексте.
Тем не менее, если у вас есть предположение о будущих расширениях, и вы хотите позволить нескольким разработчикам добавлять командные утилиты в различные модули с cmd
, то структура с __init__.py
может оказаться более подходящей.
Заключение
На основании вашего опыта и трудностей, с которыми вы столкнулись, рекомендуем реализовать один основной файл и один вспомогательный подкаталог. Это поможет избежать путаницы и обеспечит более чистую архитектуру. Ваши текущие проблемы, вероятно, возникли из-за смешивания двух методов. Попробуйте пересмотреть вашу архитектуру с учетом указаний выше, и это должно значительно улучшить вашу организацию проекта.
Если у вас возникнут дополнительные вопросы или вам нужна помощь в дальнейших этапах разработки, всегда рады помочь! Удачи в программировании!