Korzystając już z płaskich pakietów, nie spodziewałem się problemu z pakietami zagnieżdżonymi. Tutaj jest…
Układ katalogu
dir
|
+-- test.py
|
+-- package
|
+-- __init__.py
|
+-- subpackage
|
+-- __init__.py
|
+-- module.py
Zawartość init .py
Obie package/__init__.py
i package/subpackage/__init__.py
są puste.
Zadowolony z module.py
# file `package/subpackage/module.py`
attribute1 = "value 1"
attribute2 = "value 2"
attribute3 = "value 3"
# and as many more as you want...
Zawartość test.py
(3 wersje)
Wersja 1
# file test.py
from package.subpackage.module import *
print attribute1 # OK
To zły i niebezpieczny sposób importowania rzeczy (importuj wszystko zbiorczo), ale działa.
Wersja 2
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
from module import attribute1
Bezpieczniejszy sposób importowania, pozycja po pozycji, ale zawodzi, Python nie chce tego: kończy się niepowodzeniem z komunikatem: „Brak modułu o nazwie moduł”. Jednak …
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
print module # Surprise here
… Mówi <module 'package.subpackage.module' from '...'>
. Więc to jest moduł, ale to nie jest moduł / -P 8-O ... uh
Wersja 3
# file test.py v3
from package.subpackage.module import attribute1
print attribute1 # OK
Ten działa. Więc albo jesteś zmuszony do używania przedrostka overkill przez cały czas, albo używasz niebezpiecznego sposobu, jak w wersji # 1 i zabroniony przez Python do korzystania z bezpiecznego, wygodnego sposobu? Lepszy sposób, który jest bezpieczny i pozwala uniknąć zbędnych długich przedrostków, jest jedynym, który Python odrzuca? Czy to dlatego, że kocha, import *
czy dlatego, że kocha zbyt długie przedrostki (co nie pomaga w egzekwowaniu tej praktyki)?
Przepraszam za trudne słowa, ale już dwa dni próbuję obejść to głupie zachowanie. O ile gdzieś się nie pomyliłem, będę miał wrażenie, że coś jest naprawdę zepsute w modelu pakietu i pakietów podrzędnych Pythona.
Uwagi
- Nie chcę polegać na
sys.path
globalnych efektach ubocznych ani na*.pth
plikach, które są po prostu kolejnym sposobem na zabawęsys.path
z tymi samymi efektami globalnymi. Aby roztwór był czysty, musi być tylko lokalny. Albo Python jest w stanie obsłużyć podpakiet, albo nie, ale nie powinien wymagać zabawy z konfiguracją globalną, aby móc obsługiwać lokalne rzeczy. - Próbowałem również użyć importu w
package/subpackage/__init__.py
, ale nic nie rozwiązało, robi to samo, a narzekasubpackage
nie jest znanym modułem, podczas gdyprint subpackage
mówi, że to moduł (znowu dziwne zachowanie).
Być może całkowicie się mylę - trudna opcja (wolałbym), ale to sprawia, że czuję się bardzo rozczarowany Pythonem.
Jakikolwiek inny znany sposób poza trzema, których próbowałem? Coś, o czym nie wiem?
(westchnienie)
-----% <----- edytuj ----->% -----
Dotychczasowe wnioski (po komentarzach ludzi)
W Pythonie nie ma nic podobnego do prawdziwego pakietu podrzędnego, ponieważ wszystkie odwołania do pakietów trafiają tylko do globalnego słownika, co oznacza, że nie ma lokalnego słownika, co oznacza, że nie ma możliwości zarządzania odwołaniami do lokalnego pakietu.
Musisz użyć pełnego prefiksu lub krótkiego prefiksu lub aliasu. Jak w:
Pełna wersja prefiksu
from package.subpackage.module import attribute1
# An repeat it again an again
# But after that, you can simply:
use_of (attribute1)
Wersja z krótkim prefiksem (ale z powtarzającym się prefiksem)
from package.subpackage import module
# Short but then you have to do:
use_of (module.attribute1)
# and repeat the prefix at every use place
Albo odmiana powyższego.
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
Wersja faktoryzowana
Jeśli nie masz nic przeciwko zaimportowaniu wielu encji naraz w partii, możesz:
from package.subpackage.module import attribute1, attribute2
# and etc.
Nie w moim pierwszym ulubionym guście (wolę mieć jedno oświadczenie dotyczące importu na importowany podmiot), ale może być tym, które osobiście faworyzuję.
Aktualizacja (2012-09-14):
Wreszcie wydaje się, że w praktyce jest OK, z wyjątkiem komentarza dotyczącego układu. Zamiast powyższego użyłem:
from package.subpackage.module import (
attribute1,
attribute2,
attribute3,
...) # and etc.