Python Namespace Packages05 Jan 2017
Suppose you have a great Python library called
mylib (I really hope you pick
better package names than I do), but you have some additional feature that you
don’t want to maintain in the same repository, but should be accessible through
mylib. Namespace packages provide a great mechanism for doing this, which I
will explain in this blog post.
mylib example, there is a core package with the main code:
mylib ├── mylib │ ├── __init__.py <-- top level __init__.py │ ├── code.py │ └── core │ ├── __init__.py │ └── code.py └── setup.py
and also a second package which provides a
mylib-plugin ├── mylib │ ├── __init__.py <-- top level __init__.py │ └── plugin │ ├── __init__.py │ └── code.py └── setup.py
Note, however, that neither of these packages is the ‘master’ one - they can be used together or completely in isolation.
If both of these packages were installed to a system and they did not use the namespace package mechanism, at module import time only the one found first would be imported, and the subpackages from the other one would be inaccessible. So, in this example, if the main package was found first, the plugin would be inaccessible, and vice versa.
Namespace packages overcome this by providing a hint to the import mechanism
that it should keep searching for other packages of the same name before
attempting to load any subpackages. This is done by making the top level
__init__.py files consist of exactly the single line:
You’ll also need to indicate to
setuptools in your
mylib is a namespace package. This is done with the
namespace_packages keyword argument:
and similarly, in the plugin package:
Because the top level package needs to indicate that it’s not a real package to
the import mechanism, it can’t have code in its top level
most applications, however, this is not a big problem.