为什么导入错误在第二次导入时更改为“无法导入名称”?

2024-05-18 10:09:26 发布

您现在位置:Python中文网/ 问答频道 /正文

这里有一个神秘的python问题

我正在开发一个python包,它偶尔会报告类似于ImportError: cannot import name …的导入错误。通常无法导入的模块

  • 很重要
  • 没有任何循环导入问题(我可以检测到)。

通过这个简单的例子,我可以重现类似的效果:

mypkg/__init__.py

    from . import module_a
    yarg  ## cause import error

mypkg/module_a.py

    print "imported module_a"

现在我将尝试导入包两次。请注意,第二次导入时错误会发生变化:

>>> import mypkg
Module A imported
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "mypkg/__init__.py", line 2, in <module>
    yarg
NameError: name 'yarg' is not defined
>>> import mypkg
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "mypkg/__init__.py", line 1, in <module>
    from . import module_a
ImportError: cannot import name module_a

给什么?

注意:

  • 如果我使用绝对导入,问题就解决了
  • 如果在第一次导入后删除键sys.modules['mypkg.module_a'],那么第二次导入将返回原始错误消息

Tags: nameinfrompyimportinit错误line
2条回答

我很确定问题是你的包无法加载。你在__init__.py文件中放了一些废话(yarg)。这意味着mypkg无法导入。因此,mypkg.module_a也不能导入。

我怀疑您会得到不同的错误,因为Python正在缓存模块状态。第一次尝试导入mypkg时,即使mypkg正在加载,也允许导入其子模块module_a。第二次,缓存了mypkg无法正常工作的事实,因此mypkg.module_a无法加载,因为其父包已损坏。

我可以说明是什么导致了每个import之间的差异,但是我在Python的导入过程方面不够专业,无法很好地解释为什么

>>> import sys
>>> before_import = set(sys.modules.keys())
>>> import mypkg
imported module_a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "mypkg\__init__.py", line 2, in <module>
    yarg  ## cause import error
NameError: name 'yarg' is not defined
>>> after_import = set(sys.modules.keys())
>>> after_import.difference(before_import)
set(['mypkg.module_a'])

当您import mypkg时,它成功地导入module_a,并将其添加到sys.modules。然后mypkg错误和不会被添加到sys.modules字典中。删除条目后,您可以重新导入时出现相同的错误:

>>> import sys
>>> del sys.modules['mypkg.module_a']
>>> import mypkg
imported module_a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "mypkg\__init__.py", line 2, in <module>
    yarg  ## cause import error
NameError: name 'yarg' is not defined

现在,我认为正在发生的是:

  1. import mypkg启动mypkg的导入过程

  2. 在处理mypkg时,它成功地将module_a导入为 自身的子包并将其添加到sys.modules

  3. 当它命中错误时,mypkg的导入过程失败并且没有 mypkg的条目留在sys.modules

  4. 包的连接失败,但子包成功 与后续导入冲突

对不起,这是我能理解的最清楚的了。Python的导入过程是一种黑色艺术。

相关问题 更多 >