TL; DR:
En Python 3.3 no tiene que hacer nada, simplemente no coloque ninguno __init__.py
en sus directorios de paquetes de espacio de nombres y simplemente funcionará. En pre-3.3, elija la pkgutil.extend_path()
solución sobre la anterior pkg_resources.declare_namespace()
, porque es a prueba de futuro y ya es compatible con paquetes de espacio de nombres implícitos.
Python 3.3 introduce paquetes de espacio de nombres implícitos, ver PEP 420 .
Esto significa que ahora hay tres tipos de objetos que pueden ser creados por un import foo
:
- Un módulo representado por un
foo.py
archivo
- Un paquete normal, representado por un directorio que
foo
contiene un __init__.py
archivo
- Un paquete de espacio de nombres, representado por uno o más directorios
foo
sin ningún __init__.py
archivo
Los paquetes también son módulos, pero aquí me refiero a "módulo sin paquete" cuando digo "módulo".
Primero busca sys.path
un módulo o paquete normal. Si tiene éxito, deja de buscar y crea e inicializa el módulo o paquete. Si no encontró ningún módulo o paquete normal, pero encontró al menos un directorio, crea e inicializa un paquete de espacio de nombres.
Los módulos y paquetes regulares se han __file__
configurado en el .py
archivo desde el que se crearon. Los paquetes regulares y de espacio de nombres se han __path__
establecido en el directorio o directorios a partir de los cuales fueron creados.
Cuando lo haga import foo.bar
, la búsqueda anterior se realiza primero foo
, luego, si se encontró un paquete, la búsqueda bar
se realiza foo.__path__
como la ruta de búsqueda en lugar de sys.path
. Si foo.bar
se encuentra foo
y foo.bar
se crea e inicializa.
Entonces, ¿cómo se mezclan los paquetes regulares y los paquetes de espacio de nombres? Normalmente no lo hacen, pero el antiguo pkgutil
método de paquete de espacio de nombres explícito se ha ampliado para incluir paquetes de espacio de nombres implícitos.
Si tiene un paquete regular existente que tiene un __init__.py
aspecto como este:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
... el comportamiento heredado es agregar cualquier otro paquete regular en la ruta buscada __path__
. Pero en Python 3.3, también agrega paquetes de espacio de nombres.
Para que pueda tener la siguiente estructura de directorios:
├── path1
│ └── package
│ ├── __init__.py
│ └── foo.py
├── path2
│ └── package
│ └── bar.py
└── path3
└── package
├── __init__.py
└── baz.py
... y siempre y cuando los dos __init__.py
tengan las extend_path
líneas (y path1
, path2
y path3
estén en su sys.path
) import package.foo
, import package.bar
y import package.baz
todos funcionen.
pkg_resources.declare_namespace(__name__)
no se ha actualizado para incluir paquetes de espacio de nombres implícitos.