I have a very simple namespace package (contents included below, as well as the directory layout). If I try to import namespace_repro.module
, I got the following error: AttributeError: module 'namespace_repro' has no attribute 'module'
. As far as I understand my package has a valid layout and the import should work. Interestingly, the error is present only in Python 3.6.8 and the import succeeds in Python 3.7.
I have a directory named import-error-repro
with in it a setup.py
(see below), then a nested directory path src/namespace_repro/module
, containing three files, __init__.py
, x.py
and y.py
. Their contents:
setup.py
from setuptools import find_namespace_packages, setup
setup(
name='namespace-repro',
version='0.1.0',
python_requires='>=3.6',
packages=find_namespace_packages('src'),
package_dir={'': 'src'},
zip_safe=False,
)
src/namespace_repro/module/__init__.py
:
from namespace_repro.module.x import x
src/namespace_repro/module/x.py
:
import namespace_repro.module.y as y
x = y.y
and finally src/namespace_repro/module/y.py
:
y = True
I created a brand new Python 3.6 conda environment by conda create -n namespace6 python=3.6 ipython
, then I activated it and installed the package as pip install -e ./import-error-repro
(note that -e
doesn't matter, the problem is reproducible without it). After that, I tried import namespace_repro.module
in ipython
(though the same happens in the official python interpreter). The result is
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-1-bcae5a697dad> in <module>
----> 1 import namespace_repro.module
~/namespace-repro/src/namespace_repro/module/__init__.py in <module>
----> 1 from namespace_repro.module.x import x
~/namespace-repro/src/namespace_repro/module/x.py in <module>
----> 1 import namespace_repro.module.y as y
2
3 x = y.y
AttributeError: module 'namespace_repro' has no attribute 'module'
---------------------------------------------------------------------------
The strange thing is that the import system finds namespace_repro.module
twice but fails at the third time!
Some other interesting behaviour:
In [1]: import namespace_repro.module.y as y # This doesn't work.
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-4-4035347ea59b> in <module>
----> 1 import namespace_repro.module.y as y
AttributeError: module 'namespace_repro' has no attribute 'module'
In [2]: import namespace_repro.module.y # But this one does! Why?
In [3]: dir(namespace_repro.module.y) # The error returns when we actually want to use the module.
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-3-d89bcfd9e509> in <module>
----> 1 dir(namespace_repro.module.y)
AttributeError: module 'namespace_repro' has no attribute 'module'
In [4]: from namespace_repro.module.y import y # This works fine!
In [5]: y
Out[5]: True
. import-error-repro
+-- setup.py
+-- src
| +-- namespace_repro
| | +-- module
| | | +-- __init__.py
| | | +-- x.py
| | | +-- y.py
This is CPython bug 30024, which unsurprisingly was fixed in 3.7. Note that the more idiomatic form with relative (circular) imports has worked since 3.5.