Создание нескольких модулей Python в разных каталогах, которые разделяют часть структуры пакета - PullRequest
2 голосов
/ 06 августа 2009

Я работаю над проектом Django, который содержит одно приложение. Приложение будет выпущено под лицензией GPL, поэтому я хочу разработать его отдельно от проекта - личного сайта, использующего приложение. Я пытаюсь использовать структуру пакета на основе моего доменного имени как для проекта, так и для приложения, и именно здесь я сталкиваюсь с проблемами.

Вот моя файловая структура (с файлами __init__.py, где это необходимо):

$HOME/django-sites/mydomain
$HOME/django-apps/mydomain/cms

И мой ПИТОНАТ:

$HOME/django-sites:$HOME/django-apps

Если я запускаю интерпретатор Python (из любого каталога в файловой системе), я могу импортировать классы с сайта, но не из приложения. Если я переверну порядок двух записей в PYTHONPATH (сначала приложения, затем сайты), я смогу импортировать их из приложения, но не с сайта.

Похоже, что Python пытается импортировать только из первой записи в PYTHONPATH, которая содержит первую часть имени пакета. Это верно? Это ожидаемое поведение? Если это так, я могу вставлять модули только в такие структуры пакетов, как domain / app1, domain / app2, если они находятся в одной структуре каталогов - независимо от PYTHONPATH.

Это не шоу-стопор, потому что я могу переименовать сайт, но он сильно отличается от того, что я ожидал. В руководстве по Python упоминается __path__, но я не знаю, как его использовать:

Пакеты поддерживают еще один специальный атрибут __path__. Это инициализируется как список, содержащий имя каталога, содержащего __init__.py пакета перед выполнением кода в этом файле. Эта переменная может быть изменена; это влияет на последующий поиск модулей и подпакетов, содержащихся в пакете.

Хотя эта функция не требуется часто, ее можно использовать для расширения набора модулей, найденных в пакете.

Кто-нибудь еще сталкивался с этим? Что я могу сделать с __path__, чтобы сделать эту функцию, как ожидалось?

Ответы [ 3 ]

4 голосов
/ 06 августа 2009

Вот как __path__ в пакете __init__.py предназначено для использования:

$ export PYTHONPATH=$HOME/django-sites
$ ls -d $HOME/django*
django-apps/  django-sites/ 
$ cat /tmp/django-sites/mydomain/__init__.py
import os

_components = __path__[0].split(os.path.sep)
if _components[-2] == 'django-sites':
  _components[-2] = 'django-apps'
  __path__.append(os.path.sep.join(_components))

$ python -c'import mydomain; import mydomain.foo'
foo here /tmp/django-apps/mydomain/foo.pyc
$ 

Как видите, это делает содержимое django-apps/mydomain частью пакета mydomain (чей __init__.py находится в django-sites/mydomain) - вам не нужно django-apps для sys.path для этой цели либо, если вы используете этот подход.

Может ли это быть лучше, чем тот ответ, который предлагает ответ @ defrex, может быть спорным, но поскольку пакет обогащает __path__, это довольно важная часть пакета инструментов для программиста на python, я подумал, что мне все-таки лучше его проиллюстрировать ; -.)

1 голос
/ 06 августа 2009

У вас два модуля с одинаковыми именами (mydomain). Почему бы не настроить свою PYTHONPATH таким образом?

$HOME/django-sites:$HOME/django-apps/mydomain

Это позволит избежать проблем с импортом.

1 голос
/ 06 августа 2009

Ваш анализ кажется правильным. Путь Python используется для поиска модулей для импорта; Python импортирует первый найденный файл. Я не уверен, что вы могли бы сделать, чтобы обойти это, кроме как назвать свои модули разными вещами или поместить их в одно и то же место в пути поиска.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...