Поскольку я уже использовал плоские пакеты, я не ожидал проблемы, с которой столкнулся с вложенными пакетами. Вот…
Макет каталога
dir
|
+-- test.py
|
+-- package
|
+-- __init__.py
|
+-- subpackage
|
+-- __init__.py
|
+-- module.py
Содержимое init .py
Оба package/__init__.pyи package/subpackage/__init__.pyпусты.
Содержание module.py
# file `package/subpackage/module.py`
attribute1 = "value 1"
attribute2 = "value 2"
attribute3 = "value 3"
# and as many more as you want...
Содержание test.py(3 версии)
Версия 1
# file test.py
from package.subpackage.module import *
print attribute1 # OK
Это плохой и небезопасный способ импорта вещей (импортировать все сразу), но он работает.
Версия 2
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
from module import attribute1
Более безопасный способ импорта, элемент за элементом, но он не работает, Python этого не хочет: сбой с сообщением: «Нет модуля с именем модуль». Однако …
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
print module # Surprise here
… Говорит <module 'package.subpackage.module' from '...'>. Итак, это модуль, но это не модуль / -P 8-O ... э-э
Версия 3
# file test.py v3
from package.subpackage.module import attribute1
print attribute1 # OK
Этот работает. Таким образом, вы либо вынуждены использовать префикс overkill все время, либо использовать небезопасный способ, как в версии №1, и не разрешает Python использовать безопасный удобный способ? Лучший способ, который является безопасным и избегает ненужного длинного префикса, - единственный, который отвергает Python? Это потому, что он любит import *или потому, что он любит слишком длинные префиксы (что не способствует соблюдению этой практики)?
Извините за резкие слова, но вот уже два дня я пытаюсь обойти это глупое поведение. Если я где-то не ошибся, это оставит у меня ощущение, что что-то действительно не работает в модели пакетов и подпакетов Python.
Примечания
- Я не хочу полагаться на то
sys.path, чтобы избежать глобальных побочных эффектов, или на*.pthфайлы, которые являются просто еще одним способом поигратьsys.pathс теми же глобальными эффектами. Чтобы раствор был чистым, он должен быть только локальным. Либо Python может обрабатывать подпакеты, либо нет, но ему не нужно играть с глобальной конфигурацией, чтобы иметь возможность обрабатывать локальные вещи. - Я также пробовал использовать импорт
package/subpackage/__init__.py, но он ничего не решил, он сделал то же самое и жалуется, чтоsubpackageэто не известный модуль, аprint subpackageговорит, что это модуль (опять же странное поведение).
Может быть, я сильно ошибаюсь (вариант, который я бы предпочел), но это меня сильно разочаровывает в Python.
Есть ли другой известный способ, кроме трех, которые я пробовал? Я чего-то не знаю?
(вздох)
-----% <----- редактировать ----->% -----
Заключение на данный момент (после комментариев людей)
В Python нет ничего лучше настоящего подпакета, поскольку все ссылки на пакеты относятся только к глобальному словарю, что означает отсутствие локального словаря, что означает, что нет способа управлять локальной ссылкой на пакет.
Вы должны использовать полный префикс, короткий префикс или псевдоним. Как в:
Полная версия префикса
from package.subpackage.module import attribute1
# An repeat it again an again
# But after that, you can simply:
use_of (attribute1)
Версия с коротким префиксом (но с повторяющимся префиксом)
from package.subpackage import module
# Short but then you have to do:
use_of (module.attribute1)
# and repeat the prefix at every use place
Или же вариант вышеупомянутого.
from package.subpackage import module as m
use_of (m.attribute1)
# `m` is a shorter prefix, but you could as well
# define a more meaningful name after the context
Факторизованная версия
Если вы не возражаете против одновременного импорта нескольких объектов в пакете, вы можете:
from package.subpackage.module import attribute1, attribute2
# and etc.
Не в моем первом любимом вкусе (я предпочитаю иметь один оператор импорта для каждой импортируемой сущности), но, возможно, это тот, который я лично предпочитаю.
Обновление (2012-09-14):
Наконец, на практике все в порядке, за исключением комментария о макете. Вместо приведенного выше я использовал:
from package.subpackage.module import (
attribute1,
attribute2,
attribute3,
...) # and etc.