Skip to content

Commit ff95678

Browse files
Jon Wayne Parrottncoghlan
authored andcommitted
Add topic on namespace packages (pypa#290)
1 parent ecd32fa commit ff95678

File tree

2 files changed

+242
-0
lines changed

2 files changed

+242
-0
lines changed

source/additional.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ either of our guides on :doc:`installing` or :doc:`distributing`.
2525
multi_version_install
2626
appveyor
2727
self_hosted_repository
28+
namespace_packages

source/namespace_packages.rst

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
============================
2+
Packaging namespace packages
3+
============================
4+
5+
:Page Status: Draft
6+
:Last Reviewed: 2017-05-04
7+
8+
Namespace packages allow you to split the sub-packages and modules within a
9+
single :term:`package <Import Package>` across multiple, separate
10+
:term:`distribution packages <Distribution Package>` (referred to as
11+
**distributions** in this document to avoid ambiguity). For example, if you
12+
have the following package structure:
13+
14+
.. code-block:: text
15+
16+
mynamespace/
17+
__init__.py
18+
subpackage_a/
19+
__init__.py
20+
...
21+
subpackage_b/
22+
__init__.py
23+
...
24+
module_b.py
25+
setup.py
26+
27+
And you use this package in your code like so::
28+
29+
from mynamespace import subpackage_a
30+
from mynamespace import subpackage_b
31+
32+
Then you can break these sub-packages into two separate distributions:
33+
34+
.. code-block:: text
35+
36+
mynamespace-subpackage-a/
37+
setup.py
38+
mynamespace/
39+
subpackage_a/
40+
__init__.py
41+
42+
mynamespace-subpackage-b/
43+
setup.py
44+
mynamespace/
45+
subpackage_b/
46+
__init__.py
47+
module_b.py
48+
49+
Each sub-package can now be separately installed, used, and versioned.
50+
51+
Namespace packages can be useful for a large collection of loosely-related
52+
packages (such as a large corpus of client libraries for multiple products from
53+
a single company). However, namespace packages come with several caveats and
54+
are not appropriate in all cases. A simple alternative is to use a prefix on
55+
all of your distributions such as ``import mynamespace_subpackage_a`` (you
56+
could even use ``import mynamespace_subpackage_a as subpackage_a`` to keep the
57+
import object short).
58+
59+
60+
Creating a namespace package
61+
============================
62+
63+
There are currently three different approaches to creating namespace packages:
64+
65+
#. Use `native namespace packages`_. This type of namespace package is defined
66+
in :pep:`420` and is available in Python 3.3 and later. This is recommended if
67+
packages in your namespace only ever need to support Python 3 and
68+
installation via ``pip``.
69+
#. Use `pkgutil-style namespace packages`_. This is recommended for new
70+
packages that need to support Python 2 and 3 and installation via both
71+
``pip`` and ``python setup.py install``.
72+
#. Use `pkg_resources-style namespace packages`_. This method is recommended if
73+
you need compatibility with packages already using this method or if your
74+
package needs to be zip-safe.
75+
76+
.. warning:: While native namespace packages and pkgutil-style namespace
77+
packages are largely compatible, pkg_resources-style namespace packages
78+
are not compatible with the other methods. It's inadvisable to use
79+
different methods in different distributions that provide packages to the
80+
same namespace.
81+
82+
Native namespace packages
83+
--------------------------------
84+
85+
Python 3.3 added **implicit** namespace packages from :pep:`420`. All that is
86+
required to create a native namespace package is that you just omit
87+
``__init__.py`` from the namespace package directory. An example file
88+
structure:
89+
90+
.. code-block:: text
91+
92+
setup.py
93+
mynamespace/
94+
# No __init__.py here.
95+
subpackage_a/
96+
# Sub-packages have __init__.py.
97+
__init__.py
98+
module.py
99+
100+
It is extremely important that every distribution that uses the namespace
101+
package omits the ``__init__.py`` or uses a pkgutil-style ``__init__.py``. If
102+
any distribution does not, it will cause the namespace logic to fail and the
103+
other sub-packages will not be importable.
104+
105+
Because ``mynamespace`` doesn't contain an ``__init__.py``,
106+
:func:`setuptools.find_packages` won't find the sub-package. You must
107+
explicitly list all packages in your ``setup.py``. For example:
108+
109+
.. code-block:: python
110+
111+
from setuptools import setup
112+
113+
setup(
114+
name='mynamespace-subpackage-a',
115+
...
116+
packages=['mynamespace.subpackage_a']
117+
)
118+
119+
A complete working example of two native namespace packages can be found in
120+
the `native namespace package example project`_.
121+
122+
.. _native namespace package example project:
123+
https://github.com/jonparrott/namespace-pkg-tests
124+
125+
.. note:: Because native and pkgutil-style namespace packages are largely
126+
compatible, you can use native namespace packages in the distributions that
127+
only support Python 3 and pkgutil-style namespace packages in the
128+
distributions that need to support Python 2 and 3.
129+
130+
pkgutil-style namespace packages
131+
--------------------------------
132+
133+
Python 2.3 introduced the `pkgutil`_ module and the
134+
`extend_path`_ function. This can be used to declare namespace
135+
packages that need to be compatible with both Python 2.3+ and Python 3. This
136+
is the recommended approach for the highest level of compatibility.
137+
138+
To create a pkgutil-style namespace package, you need to provide an
139+
``__init__.py`` file for the namespace package:
140+
141+
.. code-block:: text
142+
143+
setup.py
144+
mynamespace/
145+
__init__.py # Namespace package __init__.py
146+
subpackage_a/
147+
__init__.py # Sub-package __init__.py
148+
module.py
149+
150+
The ``__init__.py`` file for the namespace package needs to contain **only**
151+
the following:
152+
153+
.. code-block:: python
154+
155+
__path__ = __import__('pkgutil').extend_path(__path__, __name__)
156+
157+
**Every** distribution that uses the namespace package must include an
158+
identical ``__init__.py``. If any distribution does not, it will cause the
159+
namespace logic to fail and the other sub-packages will not be importable. Any
160+
additional code in ``__init__.py`` will be inaccessible.
161+
162+
A complete working example of two pkgutil-style namespace packages can be found
163+
in the `pkgutil namespace example project`_.
164+
165+
.. _pkgutil: https://docs.python.org/3/library/pkgutil.html
166+
.. _extend_path:
167+
https://docs.python.org/3/library/pkgutil.html#pkgutil.extend_path
168+
.. _pkgutil namespace example project:
169+
https://github.com/jonparrott/namespace-pkg-tests
170+
171+
172+
pkg_resources-style namespace packages
173+
--------------------------------------
174+
175+
`Setuptools`_ provides the `pkg_resources.declare_namespace`_ function and
176+
the ``namespace_packages`` argument to :func:`~setuptools.setup`. Together
177+
these can be used to declare namespace packages. While this approach is no
178+
longer recommended, it is widely present in most existing namespace packages.
179+
If you are creating a new distribution within an existing namespace package that
180+
uses this method then it's recommended to continue using this as the different
181+
methods are not cross-compatible and it's not advisable to try to migrate an
182+
existing package.
183+
184+
To create a pkg_resources-style namespace package, you need to provide an
185+
``__init__.py`` file for the namespace package:
186+
187+
.. code-block:: text
188+
189+
setup.py
190+
mynamespace/
191+
__init__.py # Namespace package __init__.py
192+
subpackage_a/
193+
__init__.py # Sub-package __init__.py
194+
module.py
195+
196+
The ``__init__.py`` file for the namespace package needs to contain **only**
197+
the following:
198+
199+
.. code-block:: python
200+
201+
__import__('pkg_resources').declare_namespace(__name__)
202+
203+
**Every** distribution that uses the namespace package must include an
204+
identical ``__init__.py``. If any distribution does not, it will cause the
205+
namespace logic to fail and the other sub-packages will not be importable. Any
206+
additional code in ``__init__.py`` will be inaccessible.
207+
208+
.. note:: Some older recommendations advise the following in the namespace
209+
package ``__init__.py``:
210+
211+
.. code-block:: python
212+
213+
try:
214+
__import__('pkg_resources').declare_namespace(__name__)
215+
except ImportError:
216+
__path__ = __import__('pkgutil').extend_path(__path__, __name__)
217+
218+
The idea behind this was that in the rare case that setuptools isn't
219+
available packages would fall-back to the pkgutil-style packages. This
220+
isn't advisable because pkgutil and pkg_resources-style namespace packages
221+
are not cross-compatible. If the presence of setuptools is a concern
222+
then the package should just explicitly depend on setuptools via
223+
``install_requires``.
224+
225+
Finally, every distribution must provide the ``namespace_packages`` argument
226+
to :func:`~setuptools.setup` in ``setup.py``. For example:
227+
228+
.. code-block:: python
229+
230+
from setuptools import find_packages, setup
231+
232+
setup(
233+
name='mynamespace-subpackage-a',
234+
...
235+
packages=find_packages()
236+
namespace_packages=['mynamespace']
237+
)
238+
239+
.. _setuptools: https://setuptools.readthedocs.io
240+
.. _pkg_resources.declare_namespace:
241+
https://setuptools.readthedocs.io/en/latest/setuptools.html#namespace-packages

0 commit comments

Comments
 (0)