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