6

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.

How to reproduce the problem?

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

Directory layout

. import-error-repro
+-- setup.py
+-- src
|   +-- namespace_repro
|   |   +-- module
|   |   |   +-- __init__.py
|   |   |   +-- x.py
|   |   |   +-- y.py
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
korommatyi
  • 123
  • 5
  • I have the same problem. This kind of import problem happens only on python 3.6.x . Same code working on 3.7, fails in any 3.6 version. Nobody know what is going on here with the version? – vgonisanz Nov 13 '19 at 14:57
  • You're right, I didn't know that worked. I don't know your problem. – Nearoo Nov 14 '19 at 17:35
  • code in module/* is wrong, so it never gets imported and attribute module is not created in namespace. use from . import y and from . import x and import will succeed – Pmp P. Nov 15 '19 at 20:25
  • 1
    This is [issue #30024](https://bugs.python.org/issue30024), fixed in Python 3.7.0. See the duplicate as well, which also covers this in detail. The work-around is to use `import namespace_repro.module.y`, then `y = namespace_repro.module.y`, or use `from namespace_repro.module import y`. – Martijn Pieters Nov 16 '19 at 18:39
  • What happens is that `sys.modules['namespace_repro']` and `sys.modules['namespace_repro.module']` are still in the 'importing' state, and don't yet have the requisite attributes set (there is no `sys.modules['namespace_repro'].module` yet because `sys.modules['namespace_repro.module']` is still being processed), but the `import ... as ...` machinery relies on those attributes having been set. – Martijn Pieters Nov 16 '19 at 18:43

1 Answers1

2

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.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76