TL; DR:
Su Python 3.3 non devi fare nulla, semplicemente non inserirli __init__.py
nelle directory dei pacchetti del tuo spazio dei nomi e funzionerà. Su pre-3.3, scegli la pkgutil.extend_path()
soluzione rispetto a pkg_resources.declare_namespace()
quella, perché è a prova di futuro e già compatibile con i pacchetti di spazio dei nomi impliciti.
Python 3.3 introduce pacchetti di spazi dei nomi impliciti, vedi PEP 420 .
Ciò significa che ora ci sono tre tipi di oggetti che possono essere creati da un import foo
:
- Un modulo rappresentato da un
foo.py
file
- Un pacchetto regolare, rappresentato da una directory
foo
contenente un __init__.py
file
- Un pacchetto dello spazio dei nomi, rappresentato da una o più directory
foo
senza alcun __init__.py
file
Anche i pacchetti sono moduli, ma qui intendo "modulo non pacchetto" quando dico "modulo".
Prima sys.path
cerca un modulo o un pacchetto normale. Se riesce, interrompe la ricerca e crea e inizializza il modulo o il pacchetto. Se non trova alcun modulo o pacchetto normale, ma trova almeno una directory, crea e inizializza un pacchetto dello spazio dei nomi.
Moduli e pacchetti regolari si sono __file__
impostati sul .py
file da cui sono stati creati. I pacchetti regolari e dei namespace hanno __path__
impostato la directory o le directory da cui sono stati creati.
Quando lo fai import foo.bar
, la ricerca di cui sopra avviene per prima foo
, quindi se viene trovato un pacchetto, la ricerca bar
viene eseguita foo.__path__
come percorso di ricerca anziché sys.path
. Se foo.bar
viene trovato foo
e foo.bar
viene creato e inizializzato.
Quindi come si combinano i pacchetti regolari e i pacchetti dello spazio dei nomi? Normalmente no, ma il vecchio pkgutil
metodo esplicito del pacchetto dello spazio dei nomi è stato esteso per includere pacchetti impliciti dello spazio dei nomi.
Se hai un pacchetto regolare esistente che ha un __init__.py
simile:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
... il comportamento precedente è quello di aggiungere altri pacchetti regolari sul percorso cercato al suo __path__
. Ma in Python 3.3, aggiunge anche pacchetti di spazi dei nomi.
Quindi puoi avere la seguente struttura di directory:
├── path1
│ └── package
│ ├── __init__.py
│ └── foo.py
├── path2
│ └── package
│ └── bar.py
└── path3
└── package
├── __init__.py
└── baz.py
... e fintanto che i due __init__.py
hanno le extend_path
linee (e path1
, path2
e path3
sono nella tua sys.path
) import package.foo
, import package.bar
e import package.baz
funzioneranno tutti.
pkg_resources.declare_namespace(__name__)
non è stato aggiornato per includere i pacchetti di spazio dei nomi impliciti.