如何解决 Python 3.6 中的这个导入错误?
How to resolve this import error in Python 3.6?
我有一个very simple namespace package(下面包含的内容,以及目录布局)。如果我尝试导入 namespace_repro.module
,我收到以下错误:AttributeError: module 'namespace_repro' has no attribute 'module'
。据我所知,我的包裹有一个有效的布局并且导入应该有效。有趣的是,该错误仅出现在 Python 3.6.8 中,而在 Python 3.7.
中导入成功
如何重现问题?
我有一个名为 import-error-repro
的目录,其中有一个 setup.py
(见下文),然后是一个嵌套目录路径 src/namespace_repro/module
,包含三个文件 __init__.py
, x.py
和 y.py
。他们的内容:
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
最后 src/namespace_repro/module/y.py
:
y = True
我通过 conda create -n namespace6 python=3.6 ipython
创建了一个全新的 Python 3.6 conda 环境,然后我激活了它并安装了 pip install -e ./import-error-repro
的包(注意 -e
没有重要的是,没有它,问题是可以重现的)。之后,我在 ipython
中尝试了 import namespace_repro.module
(尽管在官方 python 解释器中也发生了同样的情况)。结果是
---------------------------------------------------------------------------
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'
---------------------------------------------------------------------------
奇怪的是,导入系统发现namespace_repro.module
两次,第三次都失败了!
其他一些有趣的行为:
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
这是 CPython 错误 30024,不出所料,它已在 3.7 中修复。请注意,具有相对(循环)导入的更惯用的形式自 3.5 以来一直有效。
我有一个very simple namespace package(下面包含的内容,以及目录布局)。如果我尝试导入 namespace_repro.module
,我收到以下错误:AttributeError: module 'namespace_repro' has no attribute 'module'
。据我所知,我的包裹有一个有效的布局并且导入应该有效。有趣的是,该错误仅出现在 Python 3.6.8 中,而在 Python 3.7.
如何重现问题?
我有一个名为 import-error-repro
的目录,其中有一个 setup.py
(见下文),然后是一个嵌套目录路径 src/namespace_repro/module
,包含三个文件 __init__.py
, x.py
和 y.py
。他们的内容:
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
最后 src/namespace_repro/module/y.py
:
y = True
我通过 conda create -n namespace6 python=3.6 ipython
创建了一个全新的 Python 3.6 conda 环境,然后我激活了它并安装了 pip install -e ./import-error-repro
的包(注意 -e
没有重要的是,没有它,问题是可以重现的)。之后,我在 ipython
中尝试了 import namespace_repro.module
(尽管在官方 python 解释器中也发生了同样的情况)。结果是
---------------------------------------------------------------------------
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'
---------------------------------------------------------------------------
奇怪的是,导入系统发现namespace_repro.module
两次,第三次都失败了!
其他一些有趣的行为:
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
这是 CPython 错误 30024,不出所料,它已在 3.7 中修复。请注意,具有相对(循环)导入的更惯用的形式自 3.5 以来一直有效。