Какова наилучшая структура проекта для приложения Python?
Представьте, что вы хотите разработать нетривиальное приложение для рабочего стола (не web) для конечного пользователя в Python. Каков наилучший способ структурирования иерархии папок проекта?
Желательными функциями являются простота обслуживания, удобство использования IDE, пригодность для ветвления/слияния источника управления и простое создание пакетов установки.
В частности:
- Где вы размещаете источник?
- Где вы добавляете сценарии запуска приложений?
- Где вы устанавливаете проект IDE?
- Где вы проводите тестирование устройства/приемочного испытания?
- Где вы помещаете данные, отличные от Python, такие как файлы конфигурации?
- Где вы помещаете источники не-Python, такие как С++ для двоичных модулей расширения pyd/so?
Ответы
Ответ 1
Не имеет большого значения. Все, что сделает вас счастливым, будет работать. Существует не так много глупых правил, потому что проекты Python могут быть простыми.
-
/scripts
или /bin
для такого рода средств командной строки
-
/tests
для ваших тестов
-
/lib
для ваших библиотек на языке C
-
/doc
для большей документации
-
/apidoc
для документов API, созданных с помощью Epydoc.
И каталог верхнего уровня может содержать README, Config и whatnot.
Жесткий выбор - использовать дерево /src
или нет. Python не имеет различия между /src
, /lib
и /bin
, такими как Java или C.
Так как каталог верхнего уровня /src
рассматривается некоторыми как бессмысленный, ваш каталог верхнего уровня может быть архитектурой верхнего уровня вашего приложения.
Я рекомендую поместить все это в каталог "имя-мой-продукт". Итак, если вы пишете приложение с именем quux
, каталог, содержащий все это, называется /quux
.
Другой проект PYTHONPATH
, то может включать /path/to/quux/foo
для повторного использования модуля QUUX.foo
.
В моем случае, поскольку я использую Komodo Edit, мой IDE-cuft - это один файл .KPF. Я действительно положил это в каталог верхнего уровня /quux
и не добавлял его в SVN.
Ответ 2
Согласно Жан-Поль Кальдерону Структура файловой системы проекта Python:
Project/
|-- bin/
| |-- project
|
|-- project/
| |-- test/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- setup.py
|-- README
Ответ 3
Этот пост в блоге Жана-Поля Кальдерона обычно рассматривается как ответ в #python на Freenode.
Структура файловой системы проекта Python
делать:
- укажите каталог, связанный с вашим проектом. Например, если ваш проект называется "Twisted", назовите каталог верхнего уровня для его исходных файлов
Twisted
. Когда вы делаете релизы, вы должны указать суффикс номера версии: Twisted-2.5
. - создайте каталог
Twisted/bin
и поместите свои исполняемые файлы там, если они есть. Не указывайте им расширение .py
, даже если это исходные файлы Python. Не помещайте в них никакого кода, кроме импорта и вызова основной функции, определенной где-то еще в ваших проектах. (Слабая морщина: поскольку в Windows интерпретатор выбирается расширением файла, ваши пользователи Windows действительно нуждаются в расширении .py. Поэтому, когда вы устанавливаете пакет для Windows, вы можете добавить его. К сожалению, нет ничего сложного в том, что Я знаю, что автоматизировать этот процесс. Учитывая, что на POSIX расширение .py - это только бородавка, тогда как в Windows недостаток - это настоящая ошибка, если ваша пользовательская база включает пользователей Windows, вы можете захотеть просто иметь .py расширение везде.) - Если ваш проект выражается как один исходный файл Python, затем поместите его в каталог и назовите его чем-то, связанным с вашим проектом. Например,
Twisted/twisted.py
. Если вам нужно несколько исходных файлов, вместо этого создайте пакет (Twisted/twisted/
с пустым Twisted/twisted/__init__.py
) и поместите в него исходные файлы. Например, Twisted/twisted/internet.py
. - поместите свои юнит-тесты в подпакет вашего пакета (обратите внимание - это означает, что один исходный файл Python выше был трюком - вам всегда нужен хотя бы один файл для вашего устройства тесты). Например,
Twisted/twisted/test/
. Конечно, сделайте пакет с Twisted/twisted/test/__init__.py
. Поместите тесты в файлы типа Twisted/twisted/test/test_internet.py
. - добавить
Twisted/README
и Twisted/setup.py
для объяснения и установки вашего программного обеспечения, соответственно, если вы чувствуете себя хорошо.
Не
- поставьте свой источник в каталог с именем
src
или lib
. Это затрудняет запуск без установки. - поместите свои тесты за пределы вашего пакета Python. Это затрудняет запуск тестов с установленной версией.
- создайте пакет, в котором только имеет
__init__.py
, а затем поместите весь свой код в __init__.py
. Просто создайте модуль вместо пакета, это проще. - попробуйте придумать магические хаки, чтобы Python мог импортировать ваш модуль или пакет, не добавляя пользователя в каталог, содержащий его в свой путь импорта (через PYTHONPATH или какой-либо другой механизм). Вы не корректно обрабатываете все случаи, и пользователи будут сердиться на вас, когда ваше программное обеспечение не работает в их среде.
Ответ 4
Откройте Открыть Sourcing проект Python правильно.
Позвольте мне отвлечь часть макета проекта этой прекрасной статьи:
При настройке проекта важно, чтобы макет (или структура каталогов) был прав. Разумная компоновка означает, что потенциальным вкладчикам не приходится тратить навсегда охоту за кусочком кода; расположение файлов интуитивно. Поскольку мы имеем дело с существующим проектом, это означает, что вам, вероятно, понадобится переместить кое-что.
Пусть начинается сверху. В большинстве проектов есть несколько файлов верхнего уровня (например, setup.py, README.md, требования .txt и т.д.). Существуют три каталога, которые должны иметь каждый проект:
- Каталог docs, содержащий документацию по проекту
- Каталог с именем проекта, в котором хранится фактический пакет Python
- тестовый каталог в одном из двух мест
- В каталоге пакета, содержащем тестовый код и ресурсы
- Как автономный каталог верхнего уровня Чтобы лучше понять, как ваши файлы должны быть организованы, здесь приведен упрощенный снимок макета для одного из моих проектов, sandman:
$ pwd
~/code/sandman
$ tree
.
|- LICENSE
|- README.md
|- TODO.md
|- docs
| |-- conf.py
| |-- generated
| |-- index.rst
| |-- installation.rst
| |-- modules.rst
| |-- quickstart.rst
| |-- sandman.rst
|- requirements.txt
|- sandman
| |-- __init__.py
| |-- exception.py
| |-- model.py
| |-- sandman.py
| |-- test
| |-- models.py
| |-- test_sandman.py
|- setup.py
Как вы можете видеть, есть некоторые файлы верхнего уровня, каталог docs (сгенерированный пустой каталог, где sphinx помещает сгенерированную документацию), каталог sandman и тестовый каталог под sandman.
Ответ 5
Стоит также прочитать документацию на Python на упаковке.
http://docs.python.org/tutorial/modules.html#packages
Также убедитесь, что вы знакомы с остальной информацией на этой странице.
Ответ 6
Попробуйте запустить проект, используя шаблон python_boilerplate. В основном это соответствует лучшим практикам (например, этим здесь), но лучше подходит, если вы захотите разделить ваш проект на несколько яиц в какой-то момент (и поверьте мне, с чем-то, кроме простейших проектов, вы будете. Одна распространенная ситуация - это то, где вы должны использовать локально модифицированную версию другой библиотеки).
-
Где вы помещаете исходный код?
- Для прилично больших проектов имеет смысл разделить источник на несколько яиц. Каждое яйцо будет идти как отдельный setuptools-layout под
PROJECT_ROOT/src/<egg_name>
.
-
Где вы добавляете сценарии запуска приложений?
- Идеальным вариантом является запуск приложения script, зарегистрированный как
entry_point
в одном из яиц.
-
Где вы крепите проект IDE?
- Зависит от IDE. Многие из них хранят свои материалы в
PROJECT_ROOT/.<something>
в корне проекта, и это нормально.
-
Где вы размещаете тесты устройства/приемки?
- Каждое яйцо имеет отдельный набор тестов, хранящихся в его каталоге
PROJECT_ROOT/src/<egg_name>/tests
. Я лично предпочитаю использовать py.test
для их запуска.
-
Где вы помещаете данные, отличные от Python, такие как файлы конфигурации?
- Это зависит. Могут быть разные типы данных, отличных от Python.
- "Ресурсы", то есть данные, которые должны быть упакованы в яйце. Эти данные попадают в соответствующий каталог яиц, где-то в пространстве имен пакетов. Его можно использовать через пакет
pkg_resources
.
- "Config-files", то есть файлы, отличные от Python, которые должны рассматриваться как внешние по отношению к исходным файлам проекта, но должны быть инициализированы некоторыми значениями, когда приложение запускается. Во время разработки я предпочитаю хранить такие файлы в
PROJECT_ROOT/config
. Для развертывания могут быть разные варианты. В Windows можно использовать %APP_DATA%/<app-name>/config
, в Linux, /etc/<app-name>
или /opt/<app-name>/config
.
- Сгенерированные файлы, то есть файлы, которые могут быть созданы или изменены приложением во время выполнения. Я бы предпочел сохранить их в
PROJECT_ROOT/var
во время разработки и под /var
во время развертывания Linux.
- Где вы помещаете источники, отличные от Python, такие как С++ для бинарных модулей расширения pyd/so?
- В
PROJECT_ROOT/src/<egg_name>/native
Документация обычно входит в PROJECT_ROOT/doc
или PROJECT_ROOT/src/<egg_name>/doc
(это зависит от того, считаете ли вы, что некоторые яйца являются отдельными крупными проектами). Некоторая дополнительная конфигурация будет в таких файлах, как PROJECT_ROOT/buildout.cfg
и PROJECT_ROOT/setup.cfg
.
Ответ 7
По моему опыту, это просто вопрос итерации. Поместите свои данные и код, куда бы вы ни думали. Скорее всего, вы все равно ошибетесь. Но как только вы поймете, как именно все будет развиваться, вы можете гораздо лучше сделать такие догадки.
В отношении источников распространения у нас есть каталог кода в trunk, который содержит каталог для python и каталог для разных других языков. Лично я больше склоняюсь к тому, чтобы попытаться поместить любой код расширения в свой собственный репозиторий в следующий раз.
С учетом сказанного я возвращаюсь к своему первоначальному моменту: не делайте слишком большой сделки из этого. Поместите его где-нибудь, что, похоже, сработает для вас. Если вы найдете что-то, что не работает, оно может (и должно) быть изменено.
Ответ 8
В "Packon Packaging Authority" есть образец проекта:
https://github.com/pypa/sampleproject
Это примерный проект, который существует как помощь в руководстве пользователя Python Packaging Tutorial по упаковке и распределению проектов.
Ответ 9
Данные, отличные от python, лучше всего встроены в ваши модули Python с помощью поддержки package_data
в setuptools. Я настоятельно рекомендую использовать пакеты пространства имен для создания общих пространств имен, которые могут использоваться несколькими проектами, - как и Java-соглашение о размещении пакетов в com.yourcompany.yourproject
(и возможность иметь общее пространство имен com.yourcompany.utils
).
Re-ветвление и слияние, если вы используете достаточно хорошую систему управления версиями, она будет обрабатывать слияния даже через переименования; Базар особенно хорош в этом.
В отличие от некоторых других ответов здесь я нахожу +1 на том, что есть каталог верхнего уровня src
(с каталогами doc
и test
). Конкретные соглашения для дерева каталогов документации зависят от того, что вы используете; Sphinx, например, имеет свои собственные соглашения, которые поддерживает его инструмент быстрого запуска.
Пожалуйста, используйте инструменты setuptools и pkg_resources; это облегчает для других проектов использование определенных версий вашего кода (и для одновременной установки нескольких версий с разными файлами без кода, если вы используете package_data
).