Python: импорт подпакета или субмодуля
Уже использовав плоские пакеты, я не ожидал, что возникнет проблема с вложенными пакетами. Вот & # x2026;
Directory layoutdir
|
+-- test.py
|
+-- package
|
+-- __init__.py
|
+-- subpackage
|
+-- __init__.py
|
+-- module.py
Content of 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...
Content of test.py
(3 versions)
Version 1
# file test.py
from package.subpackage.module import *
print attribute1 # OK
Это плохой и небезопасный способ импортировать вещи (импортировать все навалом), но это работает.
Version 2# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
from module import attribute1
Более безопасный способ импортировать элемент за элементом, но он терпит неудачу, Python не хочет этого: происходит сбой с сообщением: «Нет модуля с именем module». Однако & # xA0; & # x2026;
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
print module # Surprise here
& # X2026; & # xA0, говорит<module 'package.subpackage.module' from '...'>
, Так что это модуль, но это не модуль / -P 8-O ... э-э
# file test.py v3
from package.subpackage.module import attribute1
print attribute1 # OK
Этот работает. Таким образом, вы либо вынуждены все время использовать префикс overkill, либо использовать небезопасный способ, как в версии # 1, и Python запрещает использовать безопасный удобный способ? Лучший способ, который является безопасным и позволяет избежать ненужного длинного префикса, является единственным, который Python отклоняет? Это потому что любитimport *
или потому что он любит слишком длинные префиксы (что не помогает применять эту практику)?
Извините за грубые слова, но вот уже два дня я пытаюсь обойти это глупое поведение. Если я где-то полностью не ошибаюсь, у меня возникнет ощущение, что что-то действительно сломано в модели пакетов Python и вложенных пакетов.
Заметки
I don't want to rely onsys.path
, to avoid global side effects, nor on *.pth
files, which are just another way to play with sys.path
with the same global effets. For the solution to be clean, it has to be local only. Either Python is able to handle subpackage, either it's not, but it should not require to play with global configuration to be able to handle local stuff.
I also tried use imports in package/subpackage/__init__.py
, but it solved nothing, it do the same, and complains subpackage
is not a known module, while print subpackage
says it's a module (weird behavior, again).
Может быть, я совершенно не прав (такой вариант я бы предпочел), но это заставляет меня сильно разочаровываться по поводу Python.
Любой другой известный способ кроме трех я попробовал? Что-то, о чем я не знаю?
(вздох)
-----% & lt; ----- изменить ----- & gt;% -----
Conclusion so far (after people's comments)В Python нет ничего похожего на настоящий пакет sub & # x2011; все ссылки на пакеты идут только в глобальный словарь, что означает отсутствие локального словаря, что означает, что нет никакого способа управлять ссылкой на локальный пакет.
Вы должны использовать полный префикс или короткий префикс или псевдоним. Как в:
Full prefix versionfrom package.subpackage.module import attribute1
# An repeat it again an again
# But after that, you can simply:
use_of (attribute1)
Short prefix version (but repeated prefix)
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
Factorized version
Если вы не хотите импортировать сразу несколько объектов одновременно, вы можете:
from package.subpackage.module import attribute1, attribute2
# and etc.
Не в моем первом любимом вкусе (я предпочитаю иметь одно утверждение импорта для каждой импортируемой сущности), но, возможно, я буду предпочитать его лично.
Update (2012-09-14):
Наконец, на практике все в порядке, кроме как с комментарием о макете. Вместо вышеупомянутого я использовал:
from package.subpackage.module import (
attribute1,
attribute2,
attribute3,
...) # and etc.