Форум сайта python.su
Здравствуйте. Никак не могу разобраться со структурой приложения.
Есть приложение, консольная утилита на 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 исключил глобально.
Используя первую структуру проекта, мне удобно разрабатывать, тестировать, собирать, публиковать, запускать.
Используя вторую (правильную) структуру, все ломается, появляется куча проблем и геморроя, в том числе и с импортами, почему же тогда ее считают правильной? Я заметил только незначительные проблемы при установке пакета с глобальной распаковкой некоторых файлов.
Так как же быть?
Отредактировано SmartBear (Июнь 20, 2021 15:05:57)
Офлайн
> Так как же быть?
Работает — не трожь!
Офлайн
SmartBearЯ думаю, ты просто не врубаешься, что проект и то, что выкладывается в паблик, - это разные вещи абсолютно. У тебя в проекте должен быть сборщик пакета для https://pypi.org . При этом проект ты делаешь так, как нужно тебе одному. И, естественно, никакие тесты не должны идти в паблик. Тесты должны быть в проекте. Ты спросишь "а как же мне сделать так, чтобы у меня был пакет, пригодный для https://pypi.org ?", ответ очень прост - напиши скрипт для создания такого пакета из проектных файлов. Это относится не только к Python'у и https://pypi.org , но и к другим языкам с другими пабликами.
Все работало, и тут я начал читать о правильной структуре python-пакета.
Тогда я изменил структуру на:
Отредактировано py.user.next (Июнь 21, 2021 00:34:40)
Офлайн
RodegastАбсолютно с вами согласен)
> Так как же быть?Работает — не трожь!
Офлайн
py.user.nextДля pypi собираю командой python -m build, или python setup.py sdist bdist_wheel, но есть проблемы о которых я писал выше. Возможно вы имеете ввиду, проект оставить удобным для разработки, а сборщик будет собирать все в правильную структуру?
Офлайн
SmartBearДа. Твоя ошибка в том, что ты пытаешься проектную структуру скопировать в пакетную структуру. А надо собрать пакетную структуру скриптом из файлов проекта и потом из этой пакетной структуры собрать пакет.
Возможно вы имеете ввиду, проект оставить удобным для разработки, а сборщик будет собирать все в правильную структуру?
Офлайн
Офлайн
py.user.nextХорошо. С этим немного разобрался. Но встаёт вопрос: а зачем же мне всё таки, все эти заморочки, если всё и так отлично работает. Немного подкорректировал MANIFEST.in and setup.py and setup.cfg, и проблемы вообще исчезли. Почему принято (и об этом сказано в официальной документации) использовать структуру с src? Для удобства сборки deb и им подобных? Или эта папка отсылка к структуре на других языках которым она требуется?
А надо собрать пакетную структуру скриптом из файлов проекта и потом из этой пакетной структуры собрать пакет.
Отредактировано SmartBear (Июнь 23, 2021 23:39:33)
Офлайн
slav0nic
советую начать с
https://packaging.python.org/
https://github.com/audreyfeldroy/cookiecutter-pypackage
https://github.com/pypa/sampleproject
Офлайн
SmartBearПотому что завтра оно не будет работать. Завтра тебе нужно будет добавить что-то в программу (расширить её, переделать её, выделить из неё часть куда-нибудь в отдельный проект), ты попробуешь, а там всё поломается. И ты в итоге скажешь “ой, а я не могу это добавить, потому что у меня какие-то там пакеты перестают собираться из-за этого”. У тебя нет свободы, потому что ты сковал проект. А нужно его освободить, наоборот. И для освобождения ты разрываешь связи в проекте, а не создаёшь их. Короче, у тебя проект становится зависимым от того, как у тебя там пакеты собираются какие-то. Хвост начинает вилять собакой.
Но встаёт вопрос: а зачем же мне всё таки, все эти заморочки, если всё и так отлично работает.
SmartBearЭто где? Ты не понимаешь, что проект может включать в себя десятки пакетов. И не всегда их все надо собирать. А где-то они вообще взаимоисключающие и их нельзя собирать одновременно. Так что скачивай настоящие проекты, смотри на их структуру, смотри на то, как они обслуживаются внутренне, какие там скрипты и что они делают.
Почему принято (и об этом сказано в официальной документации) использовать структуру с src?
SmartBearЭто тебе просто повезло. Но это не правило. А могли не исчезнуть проблемы. Не все эти системы сборок хорошо сделаны, не все они параметризуются хорошо. Иногда они предоставляют очень скудные возможности в плане гибкости конфигурации. При этом система сборки может что-то сделать физически, но через конфигурацию оно не настраивается. Это ситуация, когда ты сам должен конфигурировать своими силами то, что не расчитано на конфигурирование (ну, не доработали программисты, которые там её разрабатывали, поленились сделать что-то, оставили на потом). Ну, и что ты будешь делать тогда? Ты будешь искать другую систему сборки, где есть это конфигурирование. Потому что сам ты себе всё сделать не можешь; тебе дяденьки всё время должны давать библиотечки там всякие, системы сборок и тому подобное.
Немного подкорректировал MANIFEST.in and setup.py and setup.cfg, и проблемы вообще исчезли.
Отредактировано py.user.next (Июнь 24, 2021 01:11:18)
Офлайн