Avendo già utilizzato i pacchetti flat, non mi aspettavo il problema riscontrato con i pacchetti nidificati. Qui è…
Layout delle directory
dir
|
+-- test.py
|
+-- package
|
+-- __init__.py
|
+-- subpackage
|
+-- __init__.py
|
+-- module.py
Contenuto di init .py
Entrambi package/__init__.py
e package/subpackage/__init__.py
sono vuoti.
Il contenuto di module.py
# file `package/subpackage/module.py`
attribute1 = "value 1"
attribute2 = "value 2"
attribute3 = "value 3"
# and as many more as you want...
Contenuto di test.py
(3 versioni)
Versione 1
# file test.py
from package.subpackage.module import *
print attribute1 # OK
Questo è il modo cattivo e pericoloso di importare le cose (importa tutto in blocco), ma funziona.
Versione 2
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
from module import attribute1
Un modo più sicuro per importare, elemento per elemento, ma fallisce, Python non vuole questo: fallisce con il messaggio: "Nessun modulo denominato modulo". Però …
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
print module # Surprise here
... dice <module 'package.subpackage.module' from '...'>
. Quindi questo è un modulo, ma non è un modulo / -P 8-O ... uh
Versione 3
# file test.py v3
from package.subpackage.module import attribute1
print attribute1 # OK
Questo funziona. Quindi sei costretto a usare il prefisso overkill tutto il tempo o usi il modo non sicuro come nella versione # 1 e non sei autorizzato da Python a usare il modo comodo e sicuro? Il modo migliore, che è sicuro ed evita inutili lunghi prefissi è l'unico che Python rifiuta? È perché ama import *
o perché ama i prefissi troppo lunghi (il che non aiuta a far rispettare questa pratica) ?.
Scusa per le parole dure, ma sono due giorni che cerco di aggirare questo comportamento stupido. A meno che non mi sia sbagliato completamente da qualche parte, questo mi lascerà con la sensazione che qualcosa sia davvero rotto nel modello di pacchetto e sotto-pacchetti di Python.
Appunti
- Non voglio fare affidamento su
sys.path
, per evitare effetti collaterali globali, né sui*.pth
file, che sono solo un altro modo per giocaresys.path
con gli stessi effetti globali. Affinché la soluzione sia pulita, deve essere solo locale. O Python è in grado di gestire il sottopacchetto, o non lo è, ma non dovrebbe richiedere di giocare con la configurazione globale per essere in grado di gestire cose locali. - Ho anche provato a usare le importazioni in
package/subpackage/__init__.py
, ma non ha risolto nulla, fa lo stesso e si lamentasubpackage
non è un modulo noto, mentreprint subpackage
dice che è un modulo (comportamento strano, di nuovo).
Può darsi che mi sbagli completamente (l'opzione che preferirei), ma questo mi fa sentire molto deluso da Python.
Qualche altro modo conosciuto oltre ai tre che ho provato? Qualcosa che non so?
(sospiro)
-----% <----- modifica ----->% -----
Conclusione finora (dopo i commenti delle persone)
Non c'è niente come un vero sotto-pacchetto in Python, poiché tutti i riferimenti ai pacchetti vanno solo a un dizionario globale, il che significa che non c'è un dizionario locale, il che implica che non c'è modo di gestire il riferimento al pacchetto locale.
Devi usare il prefisso completo o il prefisso breve o l'alias. Come in:
Versione con prefisso completo
from package.subpackage.module import attribute1
# An repeat it again an again
# But after that, you can simply:
use_of (attribute1)
Versione con prefisso breve (ma prefisso ripetuto)
from package.subpackage import module
# Short but then you have to do:
use_of (module.attribute1)
# and repeat the prefix at every use place
Oppure, una variazione di quanto sopra.
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
Versione fattorizzata
Se non ti dispiace importare più entità contemporaneamente in un batch, puoi:
from package.subpackage.module import attribute1, attribute2
# and etc.
Non nel mio primo gusto preferito (preferisco avere una dichiarazione di importazione per entità importata), ma potrebbe essere quella che preferirò personalmente.
Aggiornamento (2012-09-14):
Finalmente sembra essere OK in pratica, tranne che con un commento sul layout. Invece di quanto sopra, ho usato:
from package.subpackage.module import (
attribute1,
attribute2,
attribute3,
...) # and etc.