Упаковка питона с круговым импортом - PullRequest
1 голос
/ 13 января 2012

Я просматривал предыдущие вопросы по этому поводу, но моя ситуация немного отличается ...

У меня есть каталог, который содержит несколько классов Python, которые импортируют друг друга здесь и там, где это необходимо. Я хотел бы начать упаковывать их в более мелкие модули, в основном для целей организации. Центральный компонент пакета настраивает приложение wsgi, а затем дополнительные модули предоставляют ему функциональность (до сих пор это прекрасно работало, поскольку я могу тестировать моды по отдельности в командной строке, прежде чем подключать их входные данные к веб-приложению.)

Я понимаю, как работает модуль __init__.py, его пространство имен и когда он освобождает управление. У меня проблемы с тем, что модули в некоторых случаях импортируют друг друга.

Например, у меня есть JSONEncoder, который используется в качестве аргумента cls для многих вызовов json.dumps() Этот класс используется практически в каждом файле. Если бы я переместил некоторые из этих модулей в подкаталоги в пакете, как бы я пошел «на один уровень вверх», чтобы импортировать кодер json? Нужно ли помещать родительский каталог в PYTHONPATH в каждом файле? Было бы лучше предоставить кодировщику также свой собственный каталог с отдельным файлом __init__.py?

В качестве альтернативы, мне лучше было бы добавить функцию, которая просматривает все каталоги ниже текущего рабочего каталога и добавляет их к пути?

В настоящее время основной каталог, содержащий весь код, сам по себе не является пакетом ... каков наилучший подход к переносу аналогичных классов в подкаталоги с учетом того, что они имеют циклический импорт?

EDIT:

Для уточнения:

Основным рабочим каталогом, который я разрабатывал, является обычный каталог, содержащий около десяти файлов .py, каждый из которых содержит классы с именами, такими как имена файлов. В настоящее время все это просто репозиторий .py файлов.

-project
  search.py
  jsonencoder.py
  webapp.py
  modela.py
  modelb.py
  modelc.py

Имена, конечно, для примера.

Теперь, насколько я понимаю (что может быть совершенно неправильно), разумно было бы объединить эти модели, верно?

-project
  search.py
  jsonencoder.py
  webapp.py
  -models
    __init__.py
    modela.py
    modelb.py
    modelc.py

Но, в свою очередь, понадобится ли папке project также __init__? Как бы модела, которая использует jsonencoder, импортировала ее?

Ответы [ 2 ]

1 голос
/ 13 января 2012

Ответ довольно прост:

просто используйте полное имя нужного субмодуля

Например, под

mybundle/test/__init__.py 

вы можете иметьВ строке

import mybundle.JSONEncoder
  • все будет сделано правильно.

Например, с учетом структуры этого модуля:

├── mybundle
│   ├── __init__.py
│   ├── jsonencoder
│   │   ├── __init__.py
│   └── test
│       ├── __init__.py

сфайлы, определенные как:

[gwidion@powerpuff tmp]$ cat mybundle/__init__.py
import test

[gwidion@powerpuff tmp]$ cat mybundle/test/__init__.py
import mybundle.jsonencoder

[gwidion@powerpuff tmp]$ cat mybundle/jsonencoder/__init__.py
print 5

Это работает:

[gwidion@powerpuff tmp]$ python
Python 2.7.1 (r271:86832, Apr 12 2011, 16:15:16) 
[GCC 4.6.0 20110331 (Red Hat 4.6.0-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import mybundle
5
>>> 
0 голосов
/ 13 января 2012

Вы можете попробовать что-то вроде этого (root - это ваш рабочий каталог):

/root
  - file_a.py
  - file_b.py
  /JSONEncoder 
    - __init__.py
    - JSONEncoder.py

__init__.py пусто или имеет pass или комментарий или что-то ещеЗатем вы можете сделать (из file_a.py или что-то в root):

from JSONEncoder import JSONEncoder

и иметь доступ к JSONEncoder в file_a.py.Вам не нужно прикасаться к PYTHONPATH, если весь ваш исполняемый код находится в /root, а __init__.py требуется только в подкаталогах.Этот тип макета каталога очень полезен, поскольку вы можете скрыть код, который «просто работает», и сосредоточиться на коде, с которым вам нужно работать.

...