如何修复:"ImportError无法导入名称X"

229 阅读4分钟

目录

简介

在这篇文章中,你将了解另一个导入错误,这个错误在你处理 Python 中的包和依赖关系时经常发生。

💡快速回顾一下导入语句和导入错误。

在 Python 中,import 语句有两个主要用途。

  • 它用于搜索由其名称指定的模块,然后如果模块是必需的,就加载并初始化它。
  • 它还在 import 语句的范围内定义了一个本地名字空间的名字。然后这个本地名称将能够在整个代码中用来引用被访问的模块。

如果导入语句在成功导入一个模块时遇到困难,它会引发一个 导入错误.通常,这样的问题是由于错误的安装或无效的路径造成的,这通常会引发一个. 模块未找到错误Python 3.6 和较新的版本中。

问题的提出

在 Python 中,**"ImportError: cannot import name "**错误通常发生在导入的类无法访问,或者导入的类处于循环依赖关系中。以下是发生 "ImportError: cannot import name "的主要原因

  • 导入的类处于一个循环依赖关系中。
  • 导入的类不可用或未被创建。
  • 导入的类被拼错了。
  • 从特定模块导入的类位置错误。
  • 导入的类不存在于 Python 库中。这通常发生在导入外部库的时候。

例子 :考虑到你有两个模块:x.py 和 y.py,如下所示。这些文件代表了当它们之间存在循环依赖关系时,ImportError 是如何发生的,导致了死循环的情况。

x.py

from x import x_1


def y_1():
    print('y1')
    x_1()


def y_2():
    print('y2')


if __name__ == '__main__':
    y_1()

y.py

from y import y_2


def x_1():
    print('x1')
    y_2()

输出

ImportError: cannot import name 'x_1' from partially initialized module 'x' (most likely due to a circular import)

错误的发生是因为两个Python文件,即x和y,都试图同时加载对方。y模块试图加载x模块,而x模块试图加载**y模块。**这就产生了循环加载依赖,导致了堆内存中的一个错误。为了消除ImportError ,你必须摆脱循环依赖关系。

解决方案1:简单使用导入 [避免从X导入Y]

简单地说,问题的发生是因为我们试图在一个模块的内容准备好/初始化之前同时从另一个模块访问其内容。这种情况的发生特别是因为你在使用。 from x import x_1from y import y_2. Python 可以检测到循环依赖关系并防止死循环。基本上发生的情况是,为模块创建一个空的占位符 (即不包含任何内容)。在循环依赖的模块被编译后,Python 会自动更新导入的模块。然而,为了使 Python 能够解决循环依赖的问题,你必须用 **import x**而不是在from 语句的帮助下导入模块的特定内容。由于你不再试图在顶层加载到模块的各个内容,Python 得到充足的时间来编译模块,从而自己处理循环依赖。

让我们看一下下面的代码,以了解它是如何工作的。

x.py

import x


def y_1():
    print('y1')
    x.x_1()


def y_2():
    print('y2')


if __name__ == '__main__':
    y_1()

y.py

import y


def x_1():
    print('x1')
    y.y_2()

输出

y1
x1
y2

解决方案2:重新排列导入语句的位置

在上面的例子中,你可以通过重新安排import 语句的顺序来避免循环依赖性。因此,你可以在后面导入y模块,而不是在x模块的开头导入y模块,如下面的片段所示。

x.py

def x_1():
    print('x1')
    y_2()


from y import y_2

输出

y1
x1
y2

结论

总结一下,你可以通过解决循环依赖关系来解决 "ImportError: Cannot import name X" 错误。你可以通过取消从模块中导入内容的 from x import y 形式,而仅仅使用 import 语句来导入整个模块。另一个解决这个错误的方法是在你的代码中相应改变导入语句的位置。