ImportError:无法导入名称X

问题:ImportError:无法导入名称X

我有四个不同的文件,分别命名为: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 ++了很长时间。我猜测该错误是由于两次导入实体引起的,一次是在主体中,一次是在物理学中,但是我不知道解决方法。有人可以帮忙吗?

I have four different files named: main, vector, entity and physics. I will not post all the code, just the imports, because I think that’s where the error is. (If you want, I can post more)

Main:

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

Entity:

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:

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

Physics:

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

I then run from main.py and I get the following error:

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

I am very new to Python but have worked with C++ for a long time. I’m guessing that the error is due to importing entity twice, once in main, and later in physics, but I don’t know a workaround. Can anyone help?


回答 0

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

You have circular dependent imports. physics.py is imported from entity before class Ent is defined and physics tries to import entity that is already initializing. Remove the dependency to physics from entity module.


回答 1

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

例如:

import SomeModule

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

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

While you should definitely avoid circular dependencies, you can defer imports in python.

for example:

import SomeModule

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

this ( at least in some instances ) will circumvent the error.


回答 2

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

This is a circular dependency. It can be solved without any structural modifications to the code. The problem occurs because in vector you demand that entity be made available for use immediately, and vice versa. The reason for this problem is that you asking to access the contents of the module before it is ready — by using from x import y. This is essentially the same as

import x
y = x.y
del x

Python is able to detect circular dependencies and prevent the infinite loop of imports. Essentially all that happens is that an empty placeholder is created for the module (ie. it has no content). Once the circularly dependent modules are compiled it updates the imported module. This is works something like this.

a = module() # import a

# rest of module

a.update_contents(real_a)

For python to be able to work with circular dependencies you must use import x style only.

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

Since you are no longer referring to the contents of the module at the top level, python can compile the module without actually having to access the contents of the circular dependency. By top level I mean lines that will be executed during compilation as opposed to the contents of functions (eg. y = x.y). Static or class variables accessing the module contents will also cause problems.


回答 3

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

如果您不想更改逻辑,则可以将导致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

To make logic clear is very important. This problem appear, because the reference become a dead loop.

If you don’t want to change the logic, you can put the some import statement which caused ImportError to the other position of file, for example the end.

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

You will get Import Error: ImportError: cannot import name 'a1'

But if we change the position of from test.b import b2 in A like below:

a.py

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

from test.b import b2

And the we can get what we want:

b1
a1
b2

回答 4

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

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

This is a circular dependency. we can solve this problem by using import module or class or function where we needed. if we use this approach, we can fix circular dependency

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

回答 5

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

from my_sub_module import my_function

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

I just got this error too, for a different reason…

from my_sub_module import my_function

The main script had Windows line endings. my_sub_module had UNIX line endings. Changing them to be the same fixed the problem. They also need to have the same character encoding.


回答 6

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

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

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

from my_module import Tree

def func(arg: Tree):
    # code

做:

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

(注意删除的import语句)

As already mentioned, this is caused by a circular dependency. What has not been mentioned is that when you’re using Python typing module and you import a class only to be used to annotate Types, you can use Forward references:

When a type hint contains names that have not been defined yet, that definition may be expressed as a string literal, to be resolved later.

and remove the dependency (the import), e.g. instead of

from my_module import Tree

def func(arg: Tree):
    # code

do:

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

(note the removed import statement)


回答 7

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

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

例:

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

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

Don’t name your current python script with the name of some other module you import

Solution: rename your working python script

Example:

  1. you are working in medicaltorch.py
  2. in that script, you have: from medicaltorch import datasets as mt_datasets where medicaltorch is supposed to be an installed module

This will fail with the ImportError. Just rename your working python script in 1.


回答 8

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

我收到此错误

ImportError:无法导入名称IMPLICIT_WAIT

因为我的变量实际上是IMPLICIT_TIMEOUT

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

Don’t see this one here yet – this is incredibly stupid, but make sure you’re importing the correct variable/function.

I was getting this error

ImportError: cannot import name IMPLICIT_WAIT

because my variable was actually IMPLICIT_TIMEOUT.

when I changed my import to use the correct name, I no longer got the error 🤦‍♂️


回答 9

如果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__'

If you are importing file1.py from file2.py and used this:

if __name__ == '__main__':
    # etc

Variables below that in file1.py cannot be imported to file2.py because __name__ does not equal __main__!

If you want to import something from file1.py to file2.py, you need to use this in file1.py:

if __name__ == 'file1':
    # etc

In case of doubt, make an assert statement to determine if __name__=='__main__'


回答 10

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

  1. 你会得到类似:

    python ./main.py

    ImportError:无法导入名称A

  2. 然后您启动:

    python ./modules/a.py

    ImportError:无法导入名称B

  3. 然后您启动:

    python ./modules/b.py

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

One way to track import error is step by step trying to run python on each of imported files to track down bad one.

  1. you get something like:

    python ./main.py
    

    ImportError: cannot import name A

  2. then you launch:

    python ./modules/a.py
    

    ImportError: cannot import name B

  3. then you launch:

    python ./modules/b.py
    

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


回答 11

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

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

Also not directly relevant to the OP, but failing to restart a PyCharm Python console, after adding a new object to a module, is also a great way to get a very confusing ImportError: Cannot import name ...

The confusing part is that PyCharm will autocomplete the import in the console, but the import then fails.


回答 12

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

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

In my case, I was working in a Jupyter notebook and this was happening due the import already being cached from when I had defined the class/function inside my working file.

I restarted my Jupyter kernel and the error disappeared.


回答 13

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

Not specifically for this asker, but this same error will show if the class name in your import doesn’t match the definition in the file you’re importing from.


回答 14

问题很明显:和模块中的名称之间存在循环依赖关系。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!

The problem is clear: circular dependency between names in entity and physics modules.

Regardless of importing the whole module or just a class, the names must be loaded .

Watch this example:

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

This will be compiled into:

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

With one slight change we can solve this:

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

This will be compiled into:

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