Какова наилучшая структура проекта для приложения 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 рассматривается некоторыми как бессмысленный, ваш каталог верхнего уровня может быть архитектурой верхнего уровня вашего приложения.

  • /foo
  • /bar
  • /baz

Я рекомендую поместить все это в каталог "имя-мой-продукт". Итак, если вы пишете приложение с именем quux, каталог, содержащий все это, называется /quux.

Другой проект PYTHONPATH, то может включать /path/to/quux/foo для повторного использования модуля QUUX.foo.

В моем случае, поскольку я использую Komodo Edit, мой IDE-cuft - это один файл .KPF. Я действительно положил это в каталог верхнего уровня /quux и не добавлял его в SVN.

Ответ 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).