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

Luk*_*uke 11 python python-import importerror

这是一个神秘的python问题:

我正在开发一个python包,偶尔会报告导入错误ImportError: cannot import name ….一般不能导入的模块

  • 是可以进口的
  • 没有任何循环导入问题(我可以检测到).

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

mypkg/__init__.py:

    from . import module_a
    yarg  ## cause import error
Run Code Online (Sandbox Code Playgroud)

mypkg/module_a.py:

    print "imported module_a"
Run Code Online (Sandbox Code Playgroud)

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

>>> 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
Run Code Online (Sandbox Code Playgroud)

是什么赋予了?

注意:

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

Mat*_*vor 7

我很能说明什么是使每个之间的差别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'])
Run Code Online (Sandbox Code Playgroud)

当你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
Run Code Online (Sandbox Code Playgroud)

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

  1. import mypkg 开始导入过程 mypkg

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

  3. 当它击中了错误,导入过程mypkg失败,因为没有进入mypkg留在sys.modules

  4. 包的结合失败但子包成功与后续导入冲突

这是我能想到的最好的,对不起.Python的导入过程是一种黑色艺术.