Пакет пространства имен в основном имеет особый эффект, когда приходит время импортировать подпакет. Вот что происходит при импорте foo.bar
- импортер просматривает
sys.path
в поисках чего-то похожего на foo
.
- когда он что-то найдет, он заглянет внутрь обнаруженного
foo
на bar
.
- , если
bar
не найдено:
- , если
foo
- нормальный пакет, ImportError
повышается, указывая, что foo.bar
не существует.
- , если
foo
является пакетом пространства имен , импортер возвращается к просмотру sys.path
для следующего совпадения foo
. ImportError
повышается, только если все пути исчерпаны.
Так вот что он делает , но не объясняет, почему вы можете этого хотеть. Предположим, вы разработали большую полезную библиотеку (foo
), но в рамках этого вы также разработали небольшую, но очень полезную утилиту (foo.bar
), которую другие программисты Python находят полезной, даже если они не используют ее. для большей библиотеки.
Вы можете распространять их вместе как один большой пакет (как вы его разработали), даже если большинство людей, использующих его, импортируют только субмодуль. Вашим пользователям было бы очень неудобно, потому что они должны были бы загрузить все это (все 200 МБ!), Даже если они действительно заинтересованы только в служебном классе из 10 строк. Если у вас есть открытая лицензия, вы, вероятно, обнаружите, что несколько человек в конечном итоге ее разветвляют, и теперь существует полдюжины расходящихся версий вашего служебного модуля.
Вы можете переписать всю свою библиотеку так, чтобы утилита находилась вне пространства имен foo
(просто bar
вместо foo.bar
). Вы сможете распространять утилиту отдельно, и некоторые из ваших пользователей будут счастливы, но это большая работа, особенно учитывая, что на самом деле пользователей используют целую библиотеку, и поэтому они Придется переписывать свои программы, чтобы использовать новые.
Так что вам действительно нужен способ установки foo.bar
самостоятельно, но, к счастью, он сосуществует с foo
, когда это тоже необходимо.
Пакет пространства имен позволяет именно это, две полностью независимые установки пакета foo
могут сосуществовать. setuptools
распознает, что эти два пакета предназначены для совместного использования, и вежливо смещает папки / файлы таким образом, что оба находятся на пути и отображаются как foo
, один из которых содержит foo.bar
, а другой содержит остальное foo
.
У вас будет два разных setup.py
скрипта, по одному для каждого. foo/__init__.py
в обоих пакетах должно указывать, что они являются пакетами пространства имен, поэтому импортер знает, что продолжить, независимо от того, какой пакет был обнаружен первым.