Python "ModuleNotFoundError" for a Namespace Package Subpackage in CI
A namespace package (PEP 420) spreads one importable name across multiple distributions or directories with no __init__.py at the shared level. The subpackage fails to import when an __init__.py shadows the namespace or only one portion is installed.
What this error means
Importing from acme.plugins import thing fails with ModuleNotFoundError: No module named acme.plugins, even though the acme top level imports. The shared namespace exists, but the specific portion is not visible to the import system.
ModuleNotFoundError: No module named 'acme.plugins'
# but: import acme -> succeeds (it is a namespace package)Common causes
An __init__.py turned the namespace into a regular package
A stray acme/__init__.py in one distribution makes acme a regular package, so Python stops merging the other portions and the sibling subpackage disappears.
Only one portion installed
The portion providing acme.plugins was never installed (or installed into a different environment), so the namespace has the top level but not that branch.
How to fix it
Remove the shadowing __init__.py
For a PEP 420 namespace, the shared level must have no __init__.py. Delete it so portions merge.
# there must be NO acme/__init__.py in any portion of the namespace
find . -path '*/acme/__init__.py' -printInstall all portions of the namespace
Install every distribution that contributes to the namespace into the same environment.
pip install acme-core acme-plugins
python -c "import acme.plugins; print(acme.plugins.__file__)"Declare the namespace in packaging config
- For setuptools, use
find_namespace_packages/[tool.setuptools.packages.find]with the namespace included. - Ensure no portion ships an
__init__.pyat the shared level. - Verify with
python -c "import acme; print(acme.__path__)"showing multiple paths.
How to prevent it
- Never add
__init__.pyat a PEP 420 namespace’s shared level. - Install every portion that contributes to the namespace.
- Use namespace-aware packaging config so all portions are discoverable.