ImportError:无法导入名称X


540

我有四个不同的文件,分别命名为:main,vector,entity和physics。我不会发布所有代码,而只会发布导入代码,因为我认为这就是错误所在。(如果需要,我可以发布更多信息)

主要:

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

实体:

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

向量:

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

物理:

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

我对Python非常陌生,但是已经使用C ++了很长时间。我猜测该错误是由于两次导入实体引起的,一次是在主体中,一次是在物理学中,但是我不知道解决方法。有人可以帮忙吗?


它们存储在哪里以及在哪些目录中的目录结构是什么?
2012年

1
看看这个答案在Python循环进口:stackoverflow.com/questions/7199466/...
格雷戈尔

一般来说,这不是一个好的编码习惯去做from <module> import <name>,或from <modlue> import *。最好在模块名称空间下导入,以防止覆盖同名引用的机会。
乔尔·科内特

1
@jsells您应该只调用类EntityVector而不是EntVect,没有理由缩短此类名称。是的,使用import vector然后x = vector.Vector(0,0,0)

7
嗨,@ Kevin,因为您对Java的了解更深,您对2008年这篇文章的印象是什么?作者的第一句话提到了循环依赖在Java中是“相当普遍的做法”吗?
HeyWatch'14年

Answers:


502

您有循环依赖进口。physics.py从定义entity类之前导入,Entphysics尝试导入entity已初始化的类。physicsentity模块中删除对的依赖。


5
除了重构代码,您无能为力。如果您未在Ent构造函数定义中引用Physics,请在Ent下移动mport。如果这样做,请添加诸如setPhysics之类的方法以在构造函数之后启用导入。
Teemu Ikonen'2

12
@jsells因为您使用C ++已有很长时间了,所以您应该知道两个类永远不要相互依赖。这在C ++中非常重要,即使它不是Python中的第一名,遵循这条规则仍然是一个非常好的主意。永远不要有两个彼此认识的班级。如果您需要有关为类创建结构的帮助,请同时发布其余代码。究竟如何(在代码方面)的EntityPhysics相互关联?我确定您要尝试的方法有一种解决方法。

7
@ user2032433这实际上取决于您“互相了解”的意思。不错,好的设计通常会产生一棵单向依赖的树,这通常是最好的方法。但是有一些例外。C ++类当然可以循环引用。(尽管它们不可能由彼此组成。)如果没有前向声明,这在Python中是一个问题,它并不总是具有C ++解决方案。
约翰·麦克法兰

93
“两个类绝不应该相互依赖”的说法是垃圾。双向(双向)导航在面向对象中非常常见。 books.google.co.uk/...
马丁Spamer

5
例如,通常使用Context类和State接口来实现State设计模式。将状态实例传递给Context实例,以便它们可以调用setState。这就要求国家了解上下文,反之亦然。这种经典构造如何“对代码不利”?实际上,这正是我在Python中苦苦挣扎的问题,但是当我在Java中实现State时并不需要。
奥基斯波

141

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

例如:

import SomeModule

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

这(至少在某些情况下)将避免该错误。


38
最好避免循环依赖
ckb

4
基于pep8,将导入方法放入内部不是好习惯
-TomSawyer

@TomSawyer为什么?
克鲁夫

@TomSawyer我不推荐这样做,但这是一个快速的解决方案,可以使您摆脱困境

117

这是一个循环依赖性。无需对代码进行任何结构修改即可解决。发生此问题的原因是,在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)。访问模块内容的静态或类变量也会引起问题。


24

弄清楚逻辑很重要。出现此问题,因为引用变成死循环。

如果您不想更改逻辑,则可以将导致ImportError的某些import语句放在文件的其他位置,例如结尾。

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'

但是,如果我们改变test.b的位置,将b2导入A如下所示:

py

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

from test.b import b2

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

b1
a1
b2

18

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

py

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

py

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

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

17

我也刚收到这个错误,原因有所不同...

from my_sub_module import my_function

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


7

如前所述,这是由 循环依赖。尚未提及的是,当您使用Python输入模块并且仅导入用于注释 Types的类时,可以使用 Forward引用

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

并删除依赖项(import),例如代替

from my_module import Tree

def func(arg: Tree):
    # code

做:

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

(注意删除的import语句)


6

不要使用您导入的其他模块的名称来命名当前的python脚本

解决方案:重命名工作的python脚本

例:

  1. 你在工作 medicaltorch.py
  2. 在该脚本中,您具有:应该from medicaltorch import datasets as mt_datasets在哪里medicaltorch安装了模块

将会失败ImportError。只需在1中重命名工作的python脚本即可。


谢谢,这解决了我遇到的问题。我使用了colorama库并将文件命名为colorama.py,因此python不知道要导入什么。更改文件名会有所帮助。
Marek Bodziony

5

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

我收到此错误

ImportError:无法导入名称IMPLICIT_WAIT

因为我的变量实际上是IMPLICIT_TIMEOUT

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


1
我准备杀死试图弄清楚为什么from PIL import Pillow不起作用的人。😠
aalaap

5

如果file1.py要从中导入file2.py并使用此功能:

if __name__ == '__main__':
    # etc

低于in的变量file1.py 不能导入file2.py因为__name__ 不相等 __main__

如果你想从进口的东西file1.pyfile2.py,你需要使用此file1.py

if __name__ == 'file1':
    # etc

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


4

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

  1. 你会得到类似:

    python ./main.py

    ImportError:无法导入名称A

  2. 然后您启动:

    python ./modules/a.py

    ImportError:无法导入名称B

  3. 然后您启动:

    python ./modules/b.py

    ImportError:无法导入名称C(某些不存在的模块或某些其他错误)


3

同样与OP没有直接关系,但是在向模块添加新对象后未能重新启动 PyCharm Python控制台也是一种使人非常困惑的好方法ImportError: Cannot import name ...

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


2

在我的情况下,我正在使用Jupyter笔记本工作,而发生这种情况的原因是,从我在工作文件中定义类/函数起,就已经缓存了导入。

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


1

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


1

问题很明显:和模块中的名称之间存在循环依赖关系。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!
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.