我能做些什么关于“输入错误:无法导入名称X”或“属性错误:…(很可能是由于循环导入)”?

我有一些代码分布在多个文件中,这些文件试图相互import,如下所示:

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

我假设错误是由于导入entity两次-一次在main.py中,后来在physics.py中-但我如何解决这个问题?


另请参见在Python中使用相互导入或循环(循环)导入时会发生什么?关于什么是允许的以及什么导致了WRT循环导入的问题的一般概述。请参见为什么循环导入似乎在调用堆栈中进一步向上工作,但随后会在更向下的位置引发导入错误?

1018187 次浏览

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

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

例如:

import SomeModule


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

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

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

我也刚收到这个错误,出于不同的原因…

from my_sub_module import my_function

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

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

如果你不想改变逻辑,你可以把一些导入语句引起的错误到文件的其他位置,例如结束。

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导入b2在A中的位置,如下所示:

a.py

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


from test.b import b2

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

b1
a1
b2

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

您应该使用您导入的其他模块的名称没有命名您当前的python脚本,因为您会收到该错误。

示例:

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

这将在ImportError中失败,因为有两件事情涉及medicaltorch

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

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

我得到了这个错误

错误:无法导入名称IMPLICIT_WAIT

因为我的变量实际上是IMPLICIT_TIMEOUT

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

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

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()

不是专门针对这个asker,但如果导入中的类名与要导入的文件中的定义不匹配,则会显示相同的错误。

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

  1. 你会得到类似的东西:

    python ./main.py
    

    输入错误:无法导入名称A

  2. 然后启动:

    python ./modules/a.py
    

    输入错误:无法导入名称B

  3. 然后启动:

    python ./modules/b.py
    

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

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

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

如果您从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__'是否

如前所述,这是由循环依赖引起的。没有提到的是,当你使用Python打字模块并且导入一个仅用于注释类型的类时,你可以使用前瞻参考

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

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

from my_module import Tree


def func(arg: Tree):
# code

做:

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

(注意删除的import语句)

问题很明显: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!

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

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

在我的情况下,只是错过了文件名:

from A.B.C import func_a (x)


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

其中D是文件。

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

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