TL; DR:
En Python 3.3 no tiene que hacer nada, simplemente no coloque ninguno __init__.pyen 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.pyarchivo
- Un paquete normal, representado por un directorio que
foocontiene un __init__.pyarchivo
- Un paquete de espacio de nombres, representado por uno o más directorios
foosin ningún __init__.pyarchivo
Los paquetes también son módulos, pero aquí me refiero a "módulo sin paquete" cuando digo "módulo".
Primero busca sys.pathun 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 .pyarchivo 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 barse realiza foo.__path__como la ruta de búsqueda en lugar de sys.path. Si foo.barse encuentra fooy foo.barse 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 pkgutilmé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__.pyaspecto 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__.pytengan las extend_pathlíneas (y path1, path2y path3estén en su sys.path) import package.foo, import package.bary import package.baztodos funcionen.
pkg_resources.declare_namespace(__name__) no se ha actualizado para incluir paquetes de espacio de nombres implícitos.