Разделить исходный код Python на отдельные каталоги?
Вот несколько различных пакетов Python, которые использует моя компания "foo.com":
com.foo.bar.web
com.foo.bar.lib
com.foo.zig.web
com.foo.zig.lib
com.foo.zig.lib.lib1
com.foo.zig.lib.lib2
Вот традиционный способ хранения исходного кода на диске:
pysrc/
com/
foo/
bar/
web/
lib/
zig/
web/
lib/
lib1/
lib2/
PYTHONPATH=pysrc
Но для организационных целей (разные команды, другой контроль версий и т. Д.) Мы хотим сохранить их следующим образом:
bar/
pysrc/
com/
foo/
bar/
web/
lib/
zig/
pysrc/
com/
foo/
zig/
web/
lib/
lib1/
lib2/
PYTHONPATH=bar/pysrc:zig/pysrc
Вопрос в том:
Есть ли проблемы с этим вторым методом организации?
Например, если мы import com.foo
где бы Python искать __init__.py
?
Будет ли смысл ссылаться на эти каталоги? например:
pysrc/
com/
foo/
bar/ -> symlink to /bar/pysrc/com/foo/
zig/ -> symlink to /zig/pysrc/com/foo/
Любые общие организационные предложения по коду приветствуются.
2 ответа
Python будет проходить через sys.path по порядку (который включает в себя PYTHONPATH, а затем некоторые), ища пакет com.foo в каждом. Первый, который он находит, он будет использовать для исключения других, в отличие от Perl или Java, которые эффективно объединяют пространства имен пакетов. Есть вещи, которые вы можете сделать, чтобы __path__
это меняет это поведение, но "первое совпадение выигрывает" - это то, как Python ведет себя "из коробки".
Пока вы сохраняете весь com.foo.bar полностью в bar /, а весь com.foo.zig целиком в zig /, у вас не должно возникнуть проблем со вторым макетом.
Читая страницу PEP 420, вы можете добавить следующее __init__.py
на общие пакеты:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
Таким образом, ваша структура каталогов будет выглядеть следующим образом (* __init__.py
файлы имеют вышеуказанный код):
myroot/
├── bar
│ └── pysrc
│ └── com
│ ├── ****__init__.py****
│ └── foo
│ ├── ****__init__.py****
│ └── bar
│ ├── __init__.py
│ ├── lib
│ │ ├── __init__.py
│ │ └── barlib.py
│ └── web
│ ├── __init__.py
│ ├── barweb.py
└── zig
└── pysrc
└── com
├── ****__init__.py****
└── foo
├── ****__init__.py****
└── zig
├── __init__.py
├── lib
│ ├── __init__.py
│ ├── lib1
│ │ ├── __init__.py
│ │ └── ziblib1.py
│ └── lib2
│ ├── __init__.py
│ └── ziblib2.py
└── web
├── __init__.py
├── zigweb.py
Установите путь Python, чтобы указать на ваш com/
справочники:
barPath=/myroot/bar/pysrc/
zigPath=/myroot/zig/pysrc/
export PYTHONPATH=$PYTHONPATH:$barPath:$zigPath
Чтобы проверить (я пробовал на 2.7.14 и 3.6.4):
from com.foo.bar.web.barweb import BarWeb
from com.foo.zig.web.zigweb import ZigWeb
b = BarWeb()
z = ZigWeb()
Не имея __init__.py
Код дает:
ImportError: No module named zig.web.zigweb