ImportError:无法导入名称 X

Posted

技术标签:

【中文标题】ImportError:无法导入名称 X【英文标题】:ImportError: Cannot import name X 【发布时间】:2012-03-04 09:12:57 【问题描述】:

我有四个不同的文件,分别命名为:main.pyvector.pyentity.pyphysics.py。我不会发布所有代码,只发布导入,因为我认为这就是错误所在(如果你愿意,我可以发布更多)。

main.py:

import time
from entity import Ent
from vector import Vect
#the rest just creates an entity and prints the result of movement

实体.py:

from vector import Vect
from physics import Physics
class Ent:
    #holds vector information and id
def tick(self, dt):
    #this is where physics changes the velocity and position vectors

vector.py:

from math import *
class Vect:
    #holds i, j, k, and does vector math

physics.py:

from entity import Ent
class Physics:
    #physics class gets an entity and does physics calculations on it.

然后我从main.py 运行并收到以下错误:

Traceback (most recent call last):
File "main.py", line 2, in <module>
    from entity import Ent
File ".../entity.py", line 5, in <module>
    from physics import Physics
File ".../physics.py", line 2, in <module>
    from entity import Ent
ImportError: cannot import name Ent

我猜测错误是由于两次导入实体造成的,一次在main.py,然后在physics.py,但我不知道解决方法。有人可以帮忙吗?

【问题讨论】:

它们的存储位置和目录的目录结构是什么? 看看这个在 python 中循环导入的答案:***.com/questions/7199466/… 一般来说,使用from &lt;module&gt; import &lt;name&gt;from &lt;modlue&gt; import * 并不是好的编码习惯。最好在模块命名空间下导入,以防止覆盖同名引用。 @jsells 你应该只调用你的类EntityVector 而不是EntVect,没有理由缩短这些名称。是的,使用import vector,然后使用x = vector.Vector(0,0,0) 嘿@Kevin,既然你更了解Java,你对这个2008 article的印象如何,作者的第一句话是指循环依赖是如何“相当普遍的做法”爪哇? 【参考方案1】:

您有循环依赖导入。 physics.py 在定义类 Ent 之前从 entity 导入,physics 尝试导入已经初始化的 entity。从entity 模块中移除对physics 的依赖。

【讨论】:

除了重构代码之外,您无能为力。如果您没有在 Ent 构造函数定义中引用 Physics,则将 mport 移动到 Ent 下方。如果这样做,请添加 setPhysics 之类的方法以在构造函数之后启用导入。 @jsells 由于您使用 C++ 已经“很长时间”,您应该知道两个类永远不应该相互依赖。这在 C++ 中非常重要,即使它不是 Python 中的第一名,遵循此规则仍然是一个非常好的主意。永远不会有两个彼此认识的班级。如果您在为您的类创建结构方面需要帮助,请也发布其余代码。 EntityPhysics 究竟是如何(就代码而言)相互关联的?我确定您尝试做的事情有解决方法。 @user2032433 这真的取决于你所说的“相互了解”是什么意思。确实,好的设计通常会产生一棵单向依赖树,这通常是最好的方法。但也有例外。 C++ 类当然可以循环引用彼此。 (尽管它们不可能由彼此组成。)如果没有前向声明,这是 Python 中的一个问题,它并不总是有 C++ 解决方案。 “两个类永远不应该相互依赖”的说法是垃圾。双向(双向)导航在面向对象中非常常见。 books.google.co.uk/… State 设计模式(例如)通常使用 Context 类和 State 接口来实现。 State 的实例被传递给 Context 实例,以便它们可以调用 setState。这需要状态了解上下文,反之亦然。这个经典结构是如何“不擅长代码”的?实际上,这正是我在 Python 中遇到的问题,但当我在 Java 中实现 State 时却不必这样做。【参考方案2】:

虽然您绝对应该避免循环依赖,但您可以在 python 中延迟导入。

例如:

import SomeModule

def someFunction(arg):
    from some.dependency import DependentClass

这(至少在某些情况下)会规避错误。

【讨论】:

最好规避循环依赖 基于 pep8,将 import 放在方法中并不是好的做法 @TomSawyer 为什么? @TomSawyer 我不推荐这个,但它是一个快速的解决方案,可以让你摆脱束缚【参考方案3】:

这是一个循环依赖。它可以在不对代码进行任何结构修改的情况下解决。出现问题是因为在vector 中,您要求entity 立即可用,反之亦然。这个问题的原因是你要求在模块准备好之前访问它的内容——通过使用from x import y。这与

import x
y = x.y
del x

Python 能够检测循环依赖并防止导入的无限循环。基本上所有发生的事情是为模块创建了一个空占位符(即它没有内容)。一旦循环依赖的模块被编译,它就会更新导入的模块。这是这样的。

a = module() # import a

# rest of module

a.update_contents(real_a)

为了使 python 能够处理循环依赖,您必须仅使用 import x 样式。

import x
class cls:
    def __init__(self):
        self.y = x.y

由于您不再引用顶层模块的内容,python 可以编译模块而无需实际访问循环依赖项的内容。顶层是指将在编译期间执行的行,而不是函数的内容(例如y = x.y)。访问模块内容的静态或类变量也会导致问题。

【讨论】:

这个答案很重要,对其他人来说也是一个更通用的解决方案。请注意,如果您要导入本地子模块(即import app.foo.bar),则需要为其命名(即import app.foo.bar as bar【参考方案4】:

逻辑清晰很重要。出现这个问题,是因为引用变成了死循环。

如果你不想改变逻辑,你可以把一些导致 ImportError 的 import 语句放到文件的其他位置,例如结尾。

a.py

from test.b import b2

def a1():
    print('a1')
    b2()

b.py

from test.a import a1

def b1():
    print('b1')
    a1()

def b2():
    print('b2')

if __name__ == '__main__':
    b1()

您将收到导入错误:ImportError: cannot import name 'a1'

但是如果我们改变 from test.b import b2 在 A 中的位置,如下所示:

a.py

def a1():
    print('a1')
    b2()

from test.b import b2

我们可以得到我们想要的:

b1
a1
b2

【讨论】:

【参考方案5】:

这是一个循环依赖。 我们可以在需要的地方使用 import 模块或类或函数来解决这个问题。 如果我们使用这种方法,我们可以修复循环依赖

A.py

from B import b2
def a1():
    print('a1')
    b2()

B.py

def b1():
   from A import a1
   print('b1')
   a1()

def b2():
   print('b2')
if __name__ == '__main__':
   b1() 

【讨论】:

【参考方案6】:

在我的例子中,我在 Jupyter 笔记本中工作,这是因为当我在工作文件中定义类/函数时,导入已经被缓存。

我重新启动了 Jupyter 内核,错误消失了。

【讨论】:

【参考方案7】:

我也遇到了这个错误,原因不同...

from my_sub_module import my_function

主脚本有 Windows 行结尾。 my_sub_module 有 UNIX 行结尾。将它们更改为相同可以解决问题。它们还需要具有相同的字符编码。

【讨论】:

【参考方案8】:

问题很明确:entityphysics 模块中的名称之间存在循环依赖

无论是导入整个模块还是只导入一个类,都必须加载名称。

观看此示例:

# a.py
import b
def foo():
  pass
b.bar()
# b.py
import a
def bar():
  pass
a.foo()

这将被编译成:

# a.py
# import b
# b.py
# import a # ignored, already importing
def bar():
  pass
a.foo()
# name a.foo is not defined!!!
# import b done!
def foo():
  pass
b.bar()
# done!

稍作改动我们就可以解决这个问题:

# a.py
def foo():
  pass
import b
b.bar()
# b.py
def bar():
  pass
import a
a.foo()

这将被编译成:

# a.py
def foo():
  pass
# import b
# b.py
def bar():
  pass
# import a # ignored, already importing
a.foo()
# import b done!
b.bar()
# done!

【讨论】:

【参考方案9】:

如前所述,这是由循环依赖引起的。没有提到的是,当您使用 Python typing 模块并导入一个仅用于注释 Types 的类时,您可以使用 Forward references:

当类型提示包含尚未定义的名称时, 定义可以表示为字符串文字,稍后再解析。

并删除依赖项(import),例如而不是

from my_module import Tree

def func(arg: Tree):
    # code

做:

def func(arg: 'Tree'):
    # code

(注意删除的import 语句)

【讨论】:

【参考方案10】:

试试这个解决方案:重命名你的工作 python 脚本

你应该用你导入的其他模块的名字来命名你当前的python脚本,因为你会得到那个错误。

例子:

    你在medicaltorch.py工作 在该脚本中,您有:from medicaltorch import X 其中medicaltorch 应该是单独安装的模块

ImportError 将失败,因为有两件事引用了medicaltorch

所以,只需在 1 中重命名您的工作 python 脚本。

【讨论】:

谢谢,这解决了我遇到的问题。我使用了 colorama 库并将文件命名为 colorama.py,所以 python 不知道要导入什么。更改文件名有帮助。【参考方案11】:

如果您从file2.py 导入file1.py 并使用了这个:

if __name__ == '__main__':
    # etc

低于file1.py的变量无法导入file2.py,因为__name__不等于__main__

如果你想从file1.py导入一些东西到file2.py,你需要在file1.py中使用这个:

if __name__ == 'file1':
    # etc

如有疑问,请发出assert 声明以确定是否__name__=='__main__'

【讨论】:

【参考方案12】:

跟踪导入错误的一种方法是逐步尝试在每个导入的文件上运行 python 以跟踪错误的文件。

    你会得到类似的东西:

    python ./main.py
    

    ImportError: 无法导入名称 A

    然后你启动:

    python ./modules/a.py
    

    ImportError: 无法导入名称 B

    然后你启动:

    python ./modules/b.py
    

    ImportError: cannot import name C (some NON-Existing module or some other error)

【讨论】:

【参考方案13】:

也与 OP 没有直接关系,但未能重新启动 PyCharm Python 控制台,在将新对象添加到模块后,也是获得非常混乱的好方法ImportError: Cannot import name ...

令人困惑的部分是 PyCharm 在控制台中自动完成导入,但导入会失败。

【讨论】:

【参考方案14】:

这里还没有看到这个 - 这非常愚蠢,但请确保您正在导入正确的变量/函数。

我遇到了这个错误

ImportError: 无法导入名称 IMPLICIT_WAIT

因为我的变量实际上是IMPLICIT_TIMEOUT

当我将导入更改为使用正确的名称时,我不再收到错误?‍♂️

【讨论】:

我已经准备好杀死一个试图找出from PIL import Pillow 不起作用的人。 ?【参考方案15】:

并非专门针对此提问者,但如果您导入的类名与您从中导入的文件中的定义不匹配,则会显示相同的错误。

【讨论】:

【参考方案16】:

就我而言,只是错过了文件名:

从 A.B.C 导入 func_a (x)

从 A.B.C.D 导入 func_a (O)

其中 D 是文件。

【讨论】:

以上是关于ImportError:无法导入名称 X的主要内容,如果未能解决你的问题,请参考以下文章

ImportError:无法导入名称“WebClient”

ImportError:无法导入名称“AFAVSignature”

ImportError:无法导入名称“评估”(来自意外导入评估)

Django 'ImportError: 无法导入名称 url'

ImportError:导入 PCA 时无法导入名称“LatentDirichletAllocation”[关闭]

如何修复“ImportError:无法导入名称'StringIO'”