ImportError: Невозможно импортировать имя X
У меня есть четыре разных файла: главный, векторный, объект и физика. Я не буду публиковать весь код, только импорт, потому что я думаю, что здесь ошибка. (Если хотите, могу выложить больше)
Главный:
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++. Я предполагаю, что ошибка происходит из-за импорта сущности дважды, один раз в основную, а затем в физике, но я не знаю обходного пути. Кто-нибудь может помочь?
18 ответов
У вас есть круговой зависимый импорт. physics.py
импортируется из entity
перед уроком Ent
определяется и physics
пытается импортировать entity
это уже инициализация. Удалить зависимость от physics
от entity
модуль.
Хотя вам определенно следует избегать циклических зависимостей, вы можете отложить импорт в 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
). Статические переменные или переменные класса, обращающиеся к содержимому модуля, также вызовут проблемы.
В моем случае я работал в записной книжке Jupyter, и это происходило из-за того, что импорт уже кэшировался, когда я определил класс / функцию внутри моего рабочего файла.
Я перезапустил ядро Jupyter, и ошибка исчезла.
Прояснить логику очень важно. Эта проблема появляется, потому что ссылка становится мертвой петлей.
Если вы не хотите изменять логику, вы можете поместить оператор import, который вызвал ImportError, в другую позицию файла, например в конец.
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'
Но если мы изменим позицию из test.b import b2 в A, как показано ниже:
a.py
def a1():
print('a1')
b2()
from test.b import b2
И мы можем получить то, что мы хотим:
b1
a1
b2
Это круговая зависимость. мы можем решить эту проблему, используя модуль импорта или класс или функцию там, где нам нужно. если мы используем этот подход, мы можем исправить круговую зависимость
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()
Я тоже получил эту ошибку, по другой причине...
from my_sub_module import my_function
Основной скрипт имел окончания строки Windows. my_sub_module
имел окончания строки UNIX. Изменение их на одно и то же решило проблему. Они также должны иметь одинаковую кодировку символов.
Как уже упоминалось, это вызвано циклической зависимостью. Что не было упомянуто, так это то, что когда вы используете модуль ввода Python и импортируете класс только для использования при аннотировании типов, вы можете использовать прямые ссылки:
Когда подсказка типа содержит имена, которые еще не были определены, это определение может быть выражено как строковый литерал, который будет разрешен позже.
и удалите зависимость (импорт), например, вместо
from my_module import Tree
def func(arg: Tree):
# code
делать:
def func(arg: 'Tree'):
# code
(обратите внимание на удаленный import
заявление)
Проблема ясна: круговая зависимость между именами вentity
а также physics
модули.
Независимо от импорта всего модуля или только класса, имена должны быть загружены.
Посмотрите этот пример:
# 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!
Не называйте свой текущий скрипт Python именем какого-либо другого модуля, который вы импортируете
Решение: переименуйте ваш рабочий скрипт на Python
Пример:
- ты работаешь в
medicaltorch.py
- в этом сценарии у вас есть:
from medicaltorch import datasets as mt_datasets
гдеmedicaltorch
должен быть установленный модуль
Это не удастся с ImportError
, Просто переименуйте ваш рабочий скрипт на Python в 1.
Если вы импортируете file1.py
от file2.py
и использовал это:
if __name__ == '__main__':
# etc
Переменные ниже, чем в file1.py
не может быть импортирован вfile2.py
потому как __name__
не равно __main__
!
Если вы хотите импортировать что-то из file1.py
к file2.py
, вам нужно использовать это в file1.py
:
if __name__ == 'file1':
# etc
В случае сомнений сделайте assert
заявление, чтобы определить, __name__=='__main__'
Также не имеет прямого отношения к OP, но невозможность перезапустить консоль PyCharm Python после добавления нового объекта в модуль также является отличным способом получить очень запутанныйImportError: Cannot import name ...
Непонятная часть заключается в том, что PyCharm автоматически завершит импорт в консоли, но затем импорт завершится неудачно.
Пока не видите этого - это невероятно глупо, но убедитесь, что вы импортируете правильную переменную / функцию.
Я получаю эту ошибку
ImportError: невозможно импортировать имя IMPLICIT_WAIT
потому что моя переменная была на самом деле IMPLICIT_TIMEOUT
,
когда я изменил свой импорт, чтобы использовать правильное имя, я больше не получил ошибку ♂️
Один из способов отследить ошибку импорта - это пошаговая попытка запустить python для каждого из импортированных файлов, чтобы отследить плохой.
вы получите что-то вроде:
python ./main.py
ImportError: невозможно импортировать имя A
затем вы запускаете:
python ./modules/a.py
ImportError: невозможно импортировать имя B
затем вы запускаете:
python ./modules/b.py
ImportError: невозможно импортировать имя C (какой-либо НЕСуществующий модуль или другая ошибка)
Не специально для этого спрашивающего, но эта же ошибка будет отображаться, если имя класса в вашем импорте не соответствует определению в файле, из которого вы импортируете.
В моем случае просто пропущенное имя файла:
из ABC импортировать func_a (x)
из ABCD импортировать func_a (O)
где D - файл.
Я тоже встречал эту ошибку, но мой случай менее распространен, и он тоже выдает эту ошибку.
В моем случае я сталкиваюсь с этой ошибкой в блокноте jupyter; Я пишуfrom M import c
гдеM
является файлом python и является классом в , причина ошибки в том, чтоc
только что создан несколько минут назад, но мой блокнот Jupyter работает уже давно, поэтому мне просто нужно перезапустить блокнот Jupyter и дать ему перезагрузитьсяM.py
.
Python чувствителен к регистру, поэтому entity
знак равно Entity
, Я предлагаю вам изменить корпус entity
в вашем импорте, чтобы быть Entity
, Это исправит вашу проблему.