In Python, a namespace package allows you to spread Python code among several projects. This is useful when you want to release related libraries as separate downloads. For example, with the directories Package-1
and Package-2
in PYTHONPATH
,
Package-1/namespace/__init__.py
Package-1/namespace/module1/__init__.py
Package-2/namespace/__init__.py
Package-2/namespace/module2/__init__.py
the end-user can import namespace.module1
and import namespace.module2
.
What's the best way to define a namespace package so more than one Python product can define modules in that namespace?
This is an old question, but someone recently commented on my blog that my posting about namespace packages was still relevant, so thought I would link to it here as it provides a practical example of how to make it go:
http://cdent.tumblr.com/post/216241761/python-namespace-packages-for-tiddlyweb
That links to this article for the main guts of what's going on:
http://www.siafoo.net/article/77#multiple-distributions-one-virtual-package
The
__import__("pkg_resources").declare_namespace(__name__)
trick is pretty much drives the management of plugins in TiddlyWeb and thus far seems to be working out.This section should be pretty self-explanatory.
In short, put the namespace code in
__init__.py
, updatesetup.py
to declare a namespace, and you are free to go.There's a standard module, called pkgutil, with which you can 'append' modules to a given namespace.
With the directory structure you've provided:
You should put those two lines in both
Package-1/namespace/__init__.py
andPackage-2/namespace/__init__.py
(*):(* since -unless you state a dependency between them- you don't know which of them will be recognized first - see PEP 420 for more information)
As the documentation says:
From now on, you should be able to distribute those two packages independently.
You have your Python namespace concepts back to front, it is not possible in python to put packages into modules. Packages contain modules not the other way around.
A Python package is simply a folder containing a
__init__.py
file. A module is any other file in a package (or directly on thePYTHONPATH
) that has a.py
extension. So in your example you have two packages but no modules defined. If you consider that a package is a file system folder and a module is file then you see why packages contain modules and not the other way around.So in your example assuming Package-1 and Package-2 are folders on the file system that you have put on the Python path you can have the following:
You now have one package
namespace
with two modulesmodule1
andmodule2
. and unless you have a good reason you should probably put the modules in the folder and have only that on the python path like below:TL;DR:
On Python 3.3 you don't have to do anything, just don't put any
__init__.py
in your namespace package directories and it will just work. On pre-3.3, choose thepkgutil.extend_path()
solution over thepkg_resources.declare_namespace()
one, because it's future-proof and already compatible with implicit namespace packages.Python 3.3 introduces implicit namespace packages, see PEP 420.
This means there are now three types of object that can be created by an
import foo
:foo.py
filefoo
containing an__init__.py
filefoo
without any__init__.py
filesPackages are modules too, but here I mean "non-package module" when I say "module".
First it scans
sys.path
for a module or regular package. If it succeeds, it stops searching and creates and initalizes the module or package. If it found no module or regular package, but it found at least one directory, it creates and initializes a namespace package.Modules and regular packages have
__file__
set to the.py
file they were created from. Regular and namespace packages have__path__
set to the directory or directories they were created from.When you do
import foo.bar
, the above search happens first forfoo
, then if a package was found, the search forbar
is done withfoo.__path__
as the search path instead ofsys.path
. Iffoo.bar
is found,foo
andfoo.bar
are created and initialized.So how do regular packages and namespace packages mix? Normally they don't, but the old
pkgutil
explicit namespace package method has been extended to include implicit namespace packages.If you have an existing regular package that has an
__init__.py
like this:... the legacy behavior is to add any other regular packages on the searched path to its
__path__
. But in Python 3.3, it also adds namespace packages.So you can have the following directory structure:
... and as long as the two
__init__.py
have theextend_path
lines (andpath1
,path2
andpath3
are in yoursys.path
)import package.foo
,import package.bar
andimport package.baz
will all work.pkg_resources.declare_namespace(__name__)
has not been updated to include implicit namespace packages.