我有一些代码分布在多个文件中,试图从彼此导入,如下所示:

main.py:

from entity import Ent

entity.py:

from physics import Physics
class Ent:
    ...

physics.py:

from entity import Ent
class Physics:
    ...

然后从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和物理。py -但我如何解决这个问题?


参见在Python中使用相互导入或循环(循环)导入时会发生什么?了解WRT循环导入所允许的内容以及导致问题的原因。参见为什么循环导入看起来在调用堆栈中更上一层,但随后在更下一层引发ImportError ?有关问题发生的原因和方式的技术细节。


你有循环依赖的导入。在定义类Ent之前从实体导入physics.py,并且physics尝试导入已经初始化的实体。从实体模块中移除对物理的依赖。


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

例如:

import SomeModule

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

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


这是一个循环依赖。不需要对代码进行任何结构修改就可以解决这个问题。出现这个问题是因为在vector中,您要求实体立即可用,反之亦然。这个问题的原因是你要求在模块准备好之前访问它的内容——通过使用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)。访问模块内容的静态变量或类变量也会导致问题。


我也得到了这个错误,因为一个不同的原因…

from my_sub_module import my_function

主脚本有Windows行结束符。my_sub_module有UNIX行结束符。将它们更改为相同的就解决了这个问题。它们还需要具有相同的字符编码。


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

如果你不想改变逻辑,你可以把导致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:不能导入名称'a1'

但是如果我们改变test的位置。b import b2 in A,如下所示:

a.py

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

from test.b import b2

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

b1
a1
b2

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

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

例子:

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

这将失败的ImportError,因为2件事涉及医疗火炬

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


这是一个循环依赖。 我们可以在需要的地方使用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() 

不是专门针对这个请求器的,但是如果导入的类名与导入的文件中的定义不匹配,同样的错误会显示出来。


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

你会得到这样的结果: python。/ main.py ImportError:不能导入名称A 然后你启动: python。/模块/ a.py ImportError:不能导入名称B 然后你启动: python。/模块/ b.py ImportError:不能导入名称C(一些不存在的模块或其他错误)


也不是直接相关的OP,但重启PyCharm Python控制台失败后,添加一个新对象到一个模块,也是一个很好的方式,得到一个非常混乱的ImportError:不能导入名称…

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


如果你从file1.py导入file1.py并使用这个:

if __name__ == '__main__':
    # etc

file1.py中低于该值的变量不能导入到file1.py中,因为__name__不等于__main__!

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

if __name__ == 'file1':
    # etc

如果有疑问,使用assert语句确定__name__=='__main__'


如前所述,这是由循环依赖关系引起的。没有提到的是,当你使用Python类型模块时,你导入一个类只用于注释类型,你可以使用Forward引用:

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

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

from my_module import Tree

def func(arg: Tree):
    # code

do:

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

(注意删除的import语句)


问题很明显:实体和物理模块中名称之间的循环依赖关系。

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

看这个例子:

# 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!

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

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


在我的例子中,只是错过了文件名:

from A.B.C import func_a (x)

from A.B.C.D import func_a (O)

其中D为file。


我也遇到过这个错误,但我的情况不太常见,它也抛出这个错误。

我的案例是,我在jupyter笔记本上遇到了这个错误;我从M导入c,其中M是一个python文件,c是M.py中的一个类,出现错误的原因是因为c是几分钟前刚刚创建的,但我的jupyter笔记本已经运行了很长时间,所以我只需要重新启动jupyter笔记本,让它重新加载M.py。