【问题标题】:Import error - what is going on?导入错误 - 发生了什么?
【发布时间】:2014-03-03 19:52:26
【问题描述】:

Python 导入。再次...

我有这个文件结构:

[test]
    start.py (from scripts import main)
    [scripts]
        __init__.py (empty)
        main.py (from . import install)
        install.py (from scripts import main # or # from . import main)

我收到导入错误:

vic@wic:~/projects/test$ python3 start.py 
Traceback (most recent call last):
  File "start.py", line 2, in <module>
    from scripts import main
  File "/home/vic/projects/test/scripts/main.py", line 1, in <module>
    from . import install
  File "/home/vic/projects/test/scripts/install.py", line 1, in <module>
    from scripts import main
ImportError: cannot import name main
vic@wic:~/projects/test$

我不明白:第一次 from scripts import main 工作(通过“工作”我的意思是它没有失败 ImportError),第二次相同的代码给出 ImportError: cannot import name main

发生了什么事?

更新:

我的问题与循环导入无关。我对完全相同的代码from scripts import main 第一次工作正常,然后第二次失败这一事实感到困惑。

我猜有一些我不明白的内部导入机制。

第一次语句导入模块,第二次完全相同的代码尝试从模块导入名称。这是如何工作的?

【问题讨论】:

  • 我不是该主题的专家,因此不太可能得到一个好的答案,但link 可能会对您有所帮助。

标签: python python-3.x


【解决方案1】:

您创建了循环导入。你不能那样做。避免从install 导入main

发生的情况是,一个模块在导入时是不完整的,直到整个顶层都执行完毕。如果在执行期间它导入另一个模块(直接或间接)尝试再次导入原始模块,这将失败。原始模块尚未完成导入。

换句话说,您正在创建一个圆形图:

start -> scripts.main -> scripts.install
              ^                |
              |                |
               ----------------

您需要重新安排您的代码,以便不需要从您的scripts 包中的main 导入。

请参阅What are the “best practices” for using import in a module? 了解有关如何处理此问题的一些提示。

【讨论】:

  • 我希望第二次能像第一次一样工作,即导入 scripts.main 并将其分配给名称 main
  • >原模块还没有完成导入。sys.modules,虽然它的导入还没有完成
  • 是的,但它不完整。 Python 不能保证您尝试导入的对象确实存在或正确定义。
  • 我理解循环导入的问题,我不会为此争论。让我困惑的是相同的代码from scripts import main 第一次可以,然后第二次失败
  • @warwaruk,第一个from scripts import main 不起作用。它失败了,出现 ImportError。它在第一次识别循环时失败,当第二个from scripts import main发生时。我认为您对回溯显示两个导入的事实感到困惑,但这并不意味着它成功通过了第一个:它正在尝试执行第一个的过程它执行显示的行并失败。
【解决方案2】:

main 导入 installinstall 导入 main

  • from scripts import main in start.py 导致
  • from . import install in main.py 导致
  • from scripts import main in install.py -- 循环导入

要解决循环导入问题,可以将 maininstall 合并到一个模块中,或者创建两个模块都可以导入的第三个模块。

【讨论】:

  • @warwaruk:我已经明确说明了顺序。 from scripts import main 没有第一次工作,因为它一开始就没有完成。
【解决方案3】:

这应该可行:

start.py:

from scripts import main

脚本/main.py:

import install

脚本/install.py:

import main

【讨论】:

  • 这和我的情况不一样。我尝试从包中导入模块,而不是从另一个模块中导入名称
【解决方案4】:

这是我用来覆盖默认行为的补丁:

import sys
import builtins
import importlib

def _import(name, globals=None, locals=None, fromlist=None, level=0, __import__=__import__):
    """A hack to to make names of imported modules to be available in the parent package before
    they are fully imported. If a module is present in sys.modules event if it's not fully
    imported, it should not be a problem.
    I.e. ``from package import module1, module2`` will create variables ``package.module1`` and
    ``package.module2`` at start of the import, not when it's finished.
    This helps in some situations with circular import.
    """
    module = __import__(name, globals, locals, fromlist, level)
    for attr in fromlist or ():
        sub_module = sys.modules.get(module.__name__ + '.' + attr)
        if sub_module:  # is this a module?
            # if subpackage is already being imported, even if not finished,
            # inject its name into the parent package
            setattr(module, attr, sub_module)
    return module

builtins.__import__ = _import

这是一个测试这个的项目:https://github.com/warvariuc/python_import_improver

【讨论】:

    猜你喜欢
    • 2013-03-07
    • 1970-01-01
    • 2013-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-31
    • 2020-11-04
    • 1970-01-01
    相关资源
    最近更新 更多