Здравствуйте. Никак не могу разобраться со структурой приложения.
Есть приложение, консольная утилита на python. Изначально структура проекта была такой:
(Все имена папок и файлов абстрактные, смысл вопроса от этого не меняется).
project/
├── app.py
├── LICENSE
├── MANIFEST.in
├── project
│ ├── cli.py
│ ├── module1.py
│ └── module2.py
├── pyproject.toml
├── README.md
├── requirements-dev.txt
├── requirements.txt
├── setup.cfg
├── setup.py
└── tox.ini
Смысл был в том, чтобы была возможность собрать пакет, опубликовать его на pypi.org и устанавливать с помощью pip. Далее запускать командой: project с нужными аргументами. Так же, можно просто скачать исходники и:
Либо запускать приложение напрямую:
1. python app.py (он импортирует main() из cli.py, и запускает, cli.py в свою очередь импортирует все что нужно из модулей).
2. Либо командой python setup.py install устанавливать локально, и запускать.
Все работало, и тут я начал читать о правильной структуре python-пакета.
Тогда я изменил структуру на:
project/
├── app.py
├── LICENSE
├── MANIFEST.in
├── pyproject.toml
├── README.md
├── requirements-dev.txt
├── requirements.txt
├── setup.cfg
├── setup.py
├── src
│ └── project
│ ├── cli.py
│ ├── module1.py
│ └── module2.py
└── tox.ini
И вот тут начались проблемы, сломались импорта, тесты перестали импортировать правильно, теперь они просят импорт from src.project.module1, но src это не пакет, а просто папка! Я должен выходит сначала устанавливать пакет локально, потом уже тестировать? Используя импорты такие: from project.module1?
App.py из корневой папки тоже вынуждено импортировать по новому используя from src.project.cli import main
В cli.py импорты так же сломались, если я использую импорт from src.project.module1 это ошибка, тем более после сборки пакета не сработает, если from project.module1это не работает при разработке, так как пакет не установлен.
Приложение:
Консольная утилита. (Cli).
Цели:
Сборка пакета, публикация на pypi.
Возможность установки pip install, и последующий запуск в командной строке.
Возможность запуска без установки, из исходников.
Вопросы:
1. Какова правильная структура такого проекта?
2. Если хранить пакет в папке src, как правильно импортировать в tests (использую pytest), как правильно импортировать между модулями внутри пакета.
3. Какие настройки нужны в setup.cfg для правильной сборки пакета.
4. Какие файлы и папки я должен указывать для добавления в пакет в MANIFEST.in, нужно ли добавлять tests?
5. Нужно ли добавлять тесты в пакет? Проблема в том, что папка tests, подтягивалась автоматически, при 1 варианте структуры пакета, она распаковывалась глобально, если установить второй похожий пакет со структурой 1 варианта, файлы в папке tests заменялись, ну и вообще такая распаковка при установке уже явно неверная.
6. Если я буду использовать верную структуру пакетов как мне импортировать при разработке, тестировании и какие импорты выставлять при сборке, как импортировать между модулями?
Добавлю, что это не просто пакет, а пакет с возможностью запуска его в командной строке. Ну и нужна поддержка запуска без установки, из исходников.
Все это работало, до использования информации с pypi.org о правильной структуре пакетов, но замечал, что пакет при установке распаковывался частично в глобальную папку (так как имел неверную структуру я полагаю). Каждый пакет устанавливается в свою папку (точнее их две), при установке моих пакетов некоторые файлы и папки распаковывалась глобально, заменяя похожие файлы из других пакетов .
При правильной структуре этих проблем нет, но есть куча проблем с импортами при разработке и т.д.
При моем первом варианте, проблем почти нет, только распаковка некоторых файлов глобально, и подтягивается папка tests, я ее в файле MANIFEST.in исключил глобально.
Используя первую структуру проекта, мне удобно разрабатывать, тестировать, собирать, публиковать, запускать.
Используя вторую (правильную) структуру, все ломается, появляется куча проблем и геморроя, в том числе и с импортами, почему же тогда ее считают правильной? Я заметил только незначительные проблемы при установке пакета с глобальной распаковкой некоторых файлов.
Так как же быть?