TL; DR:
Su Python 3.3 non devi fare nulla, semplicemente non inserirli __init__.pynelle 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.pyfile
- Un pacchetto regolare, rappresentato da una directory
foocontenente un __init__.pyfile
- Un pacchetto dello spazio dei nomi, rappresentato da una o più directory
foosenza alcun __init__.pyfile
Anche i pacchetti sono moduli, ma qui intendo "modulo non pacchetto" quando dico "modulo".
Prima sys.pathcerca 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 .pyfile 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 barviene eseguita foo.__path__come percorso di ricerca anziché sys.path. Se foo.barviene trovato fooe foo.barviene creato e inizializzato.
Quindi come si combinano i pacchetti regolari e i pacchetti dello spazio dei nomi? Normalmente no, ma il vecchio pkgutilmetodo 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__.pysimile:
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__.pyhanno le extend_pathlinee (e path1, path2e path3sono nella tua sys.path) import package.foo, import package.bare import package.bazfunzioneranno tutti.
pkg_resources.declare_namespace(__name__) non è stato aggiornato per includere i pacchetti di spazio dei nomi impliciti.