A very confusing topic is python imports and paths.
One area that makes it more confusing was the introductions of implicit namespace packages.
https://peps.python.org/pep-0420/#differences-between-namespace-packages-and-regular-packages
These are packages that are found even without an __init__.py
.
A folder can be created on the python path and that folder automatically becomes a python package. Not sure why or if this was intended but it is a fact of life in python 3.3 and later. Example:
$ mkdir holymoly
$ python
Python 3.10.6
>>> import holymoly
>>> holymoly
)>
>>> print(holymoly.__file__)
None
How to Know if a Package is An Explicit Namespace Package
-
Import it
import fixes_package
-
Check the
__file__
attributeprint(fixes_package.__file__)
If it prints None
then it is an implicit namespace package. If it does not – and prints out the location of the __init__.py
it is a regular package
Another way is to import and repl it:
>>> import fixes_package
>>> fixes_package
Implicit namespace prints:
<module 'fixes_package' (<_frozen_importlib_external._NamespaceLoader object at 0x10683bd00>)>
If would print
<module 'fixes_package' (namespace)>
in older python versions
Regular package:
<module 'fixes_package' from '~/projects/playground/implicit_namespace/fixes_package/__init__.py'>
Packaging won’t find the Namespace Packages by default
When packaging the package, the package doesn’t contain an __init__.py
sosetuptools.find_packages()
won’t find the sub-package. You must use setuptools.find_namespace_packages()
instead or explicitly list all packages in your setup.py
. Source: packaging_namespace_packages
Anthonywritescode has a good explanation of namespace packages and their caveats.
Pyproject.toml
Using pyproject.toml
and the setuptools build system backend – did pick up the implicit namespaced package from testing.
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
It appears that using setuptools.find_packages()
directly to specify the packages is the root of the namespaced packages not being packaged.