Вже використовуючи плоскі пакети, я не очікував проблеми, з якою я зіткнувся з вкладеними пакетами. Ось…
Розмітка каталогу
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, або використовувати небезпечний спосіб, як у версії No1, і заборонений 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.
Не в моєму першому улюбленому смаку (я віддаю перевагу одній заяві про імпорт на імпортовану організацію), але, можливо, це той, який я особисто підтримую.
Оновлення (14.09.2012):
Нарешті, здається, це нормально на практиці, за винятком коментарів щодо макета. Замість вищезазначеного я використав:
from package.subpackage.module import (
attribute1,
attribute2,
attribute3,
...) # and etc.