ImportError: Nie można zaimportować nazwy X

540

Mam cztery różne pliki o nazwie: main, vector, byt i fizyka. Nie opublikuję całego kodu, tylko import, ponieważ myślę, że tam właśnie jest błąd. (Jeśli chcesz, mogę dodać więcej)

Główny:

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

Jednostka:

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

Wektor:

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

Fizyka:

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

Następnie uruchamiam z main.py i pojawia się następujący błąd:

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

Jestem bardzo nowy w Pythonie, ale od dłuższego czasu pracuję z C ++. Zgaduję, że błąd wynika z dwukrotnego importowania bytu, raz głównego, a później fizyki, ale nie znam obejścia. Czy ktoś może pomóc?

jsells
źródło
Jaka jest struktura katalogów, w których są przechowywane i w których katalogach?
Ben
1
spójrz na tę odpowiedź dotyczącą importowania pętli w pythonie: stackoverflow.com/questions/7199466/…
Gregor
Ogólnie rzecz biorąc, nie jest to dobra praktyka kodowania from <module> import <name>, lub from <modlue> import *. Lepiej importować w obszarze nazw modułów, aby uniknąć ryzyka zastąpienia referencji o identycznych nazwach.
Joel Cornett
1
@jsells Powinieneś po prostu zadzwonić na zajęcia Entityi Vectorzamiast Enti Vectnie ma powodu, aby skracać takie nazwiska. I tak, użyj import vectori wtedy x = vector.Vector(0,0,0).
7
Hej @Kevin, skoro znasz lepiej Javę, jakie jest twoje zdanie na temat tego artykułu z 2008 roku, w którym pierwsze zdanie autora odnosi się do tego, jak zależności okrągłe są „dość powszechną praktyką” w Javie?
HeyWatch,

Odpowiedzi:

502

Masz import zależny od obiegu. physics.pyjest importowany entityprzed Entzdefiniowaniem klasy i physicspróbuje zaimportować, entityktóry już się inicjuje. Usuń zależność physicsod entitymodułu.

Teemu Ikonen
źródło
5
Nie możesz zrobić nic więcej niż zmienić kod. Jeśli nie odwołujesz się do fizyki w definicji konstruktora Ent, przenieś mport tuż pod Ent. Jeśli tak, dodaj metodę taką jak setPhysics, aby włączyć import po konstruktorze.
Teemu Ikonen,
12
@jsells Ponieważ pracujesz z C ++ „od dłuższego czasu”, powinieneś wiedzieć, że dwie klasy NIGDY nie powinny być od siebie zależne. Jest to niezwykle ważne w C ++ i nawet jeśli nie jest to najważniejsza rzecz w Pythonie, to nadal bardzo dobrym pomysłem jest przestrzeganie tej reguły. Nigdy nie miej nigdy dwóch klas, które się znają. Jeśli potrzebujesz pomocy w tworzeniu struktury dla swoich klas, opublikuj resztę kodu. Jak dokładnie (jeśli chodzi o kod) są Entityi Physicspołączone ze sobą? Jestem pewien, że istnieje obejście tego, co próbujesz zrobić.
7
@ user2032433 To naprawdę zależy od tego, co rozumiesz przez „znamy się”. Prawdą jest, że dobry projekt zwykle tworzy drzewo zależności jednokierunkowych i jest to zwykle najlepsze podejście. Ale są wyjątki od tego. Klasy C ++ z pewnością mogą odnosić się do siebie cyklicznie. (Chociaż nie jest możliwe, aby się ze sobą składali.) Bez deklaracji forward jest to problem w Pythonie, który nie zawsze ma rozwiązanie C ++.
John McFarlane
93
Stwierdzenie „dwie klasy NIGDY nie powinny być od siebie zależne” to śmieci. Dwukierunkowa (dwukierunkowa) nawigacja jest bardzo powszechna w orientacji obiektowej. books.google.co.uk/…
Martin Spamer
5
Wzorzec projektu stanu (na przykład) jest zwykle implementowany z klasą kontekstu i interfejsem stanu. Instancje stanu są przekazywane do instancji Context, aby mogły wywoływać setState. Wymaga to od państwa znajomości kontekstu i na odwrót. W jaki sposób ta klasyczna konstrukcja jest „zła w kodzie”? Właściwie to jest dokładnie problem, z którym walczę w Pythonie, ale nie musiałem tego robić, kiedy implementowałem stan w Javie.
Auspice
141

Chociaż zdecydowanie powinieneś unikać zależności cyklicznych, możesz odroczyć importowanie w Pythonie.

na przykład:

import SomeModule

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

to (przynajmniej w niektórych przypadkach) obejdzie błąd.

bharling
źródło
38
najlepiej obchodzić zależności kołowe
ckb
4
Opierając się na pep8, umieszczanie importu w metodzie nie jest dobrą praktyką
TomSawyer
@TomSawyer Dlaczego?
Kröw,
@TomSawyer Nie polecam tego, ale jest to szybkie rozwiązanie, które może wyciągnąć cię z sytuacji
bharling
117

Jest to zależność cykliczna. Można go rozwiązać bez żadnych zmian strukturalnych w kodzie. Problem występuje, ponieważ vectorżądasz entitynatychmiastowego udostępnienia do użycia i odwrotnie. Przyczyną tego problemu jest to, że pytasz o dostęp do zawartości modułu, zanim będzie on gotowy - za pomocą from x import y. Jest to zasadniczo to samo co

import x
y = x.y
del x

Python jest w stanie wykryć zależności cykliczne i zapobiec nieskończonej pętli importu. Zasadniczo wszystko, co się dzieje, to tworzenie pustego symbolu zastępczego dla modułu (tzn. Nie ma on żadnej zawartości). Po skompilowaniu modułów zależnych od osi aktualizuje importowany moduł. To działa coś takiego.

a = module() # import a

# rest of module

a.update_contents(real_a)

Aby python mógł pracować z zależnościami cyklicznymi, musisz używać import xtylko stylu.

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

Ponieważ nie odwołujesz się już do zawartości modułu na najwyższym poziomie, python może skompilować moduł bez konieczności uzyskiwania dostępu do zawartości zależności cyklicznej. Przez najwyższy poziom rozumiem wiersze, które zostaną wykonane podczas kompilacji, w przeciwieństwie do zawartości funkcji (np. y = x.y). Zmienne statyczne lub klasowe uzyskujące dostęp do zawartości modułu również powodują problemy.

Wydmy
źródło
24

Wyjaśnienie logiki jest bardzo ważne. Pojawia się ten problem, ponieważ odwołanie staje się martwą pętlą.

Jeśli nie chcesz zmieniać logiki, możesz umieścić instrukcję importu, która spowodowała ImportError, w innej pozycji pliku, na przykład na końcu.

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

Otrzymasz błąd importu: ImportError: cannot import name 'a1'

Ale jeśli zmienimy pozycję z test.b importuj b2 do A, jak poniżej:

a.py

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

from test.b import b2

I możemy dostać to, czego chcemy:

b1
a1
b2
g10guang
źródło
18

Jest to zależność cykliczna. możemy rozwiązać ten problem za pomocą modułu lub klasy importu lub funkcji tam, gdzie potrzebowaliśmy. jeśli zastosujemy to podejście, możemy naprawić zależność cykliczną

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() 
a.patidar
źródło
17

Właśnie dostałem ten błąd z innego powodu ...

from my_sub_module import my_function

Główny skrypt miał zakończenia linii Windows. my_sub_modulemiał zakończenia linii UNIX. Zmiana ich na takie same rozwiązała problem. Muszą także mieć to samo kodowanie znaków.

marengaz
źródło
7

Jak już wspomniano, jest to spowodowane zależnością cykliczną . Nie wspomniano jednak, że jeśli używasz modułu pisania w języku Python i importujesz klasę tylko w celu opisywania typów , możesz użyć odwołań do przodu :

Gdy podpowiedź typu zawiera nazwy, które nie zostały jeszcze zdefiniowane, definicję tę można wyrazić dosłownie jako ciąg znaków, co zostanie rozwiązane później.

i usuń zależność ( import ), np. zamiast

from my_module import Tree

def func(arg: Tree):
    # code

zrobić:

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

(zwróć uwagę na usunięte importoświadczenie)

Tomasz Bartkowiak
źródło
6

Nie nazywaj swojego obecnego skryptu python nazwą innego importowanego modułu

Rozwiązanie: zmień nazwę działającego skryptu Python

Przykład:

  1. pracujesz w medicaltorch.py
  2. w tym skrypcie masz: from medicaltorch import datasets as mt_datasetsgdzie medicaltorchpowinien być zainstalowany moduł

To się nie powiedzie z ImportError. Po prostu zmień nazwę swojego działającego skryptu Python w 1.

Paweł
źródło
Dzięki, to rozwiązuje problem, który miałem. Użyłem biblioteki colorama i nazwałem plik colorama.py, więc python nie wiedział, co zaimportować. Zmiana nazwy pliku pomaga.
Marek Bodziony
5

Nie widzę tego tutaj jeszcze - jest to niesamowicie głupie, ale upewnij się, że importujesz poprawną zmienną / funkcję.

Otrzymałem ten błąd

ImportError: nie można zaimportować nazwy IMPLICIT_WAIT

ponieważ moja zmienna była w rzeczywistości IMPLICIT_TIMEOUT.

po zmianie importu na poprawną nazwę nie pojawia się już błąd 🤦‍♂️

Nick Brady
źródło
1
Byłem gotowy zabić kogoś, kto próbuje dowiedzieć się, dlaczego from PIL import Pillownie działa. 😠
aalaap
5

Jeśli importujesz file1.pyod file2.pyi używane to:

if __name__ == '__main__':
    # etc

Zmienne poniżej tego IN file1.py nie mogą być importowane do file2.pyponieważ __name__ nie równa __main__ !

Jeśli chcesz importować coś od file1.pycelu file2.py, trzeba korzystać z tego w file1.py:

if __name__ == 'file1':
    # etc

W razie wątpliwości należy złożyć assertoświadczenie, aby ustalić, czy__name__=='__main__'

Nicolas Gervais
źródło
4

Jednym ze sposobów śledzenia błędu importu jest próba uruchomienia Pythona na każdym z importowanych plików, aby wyśledzić zły.

  1. dostajesz coś takiego:

    python ./main.py

    ImportError: nie można zaimportować nazwy A

  2. następnie uruchom:

    python ./modules/a.py

    ImportError: nie można zaimportować nazwy B

  3. następnie uruchom:

    python ./modules/b.py

    ImportError: nie można zaimportować nazwy C (niektóre nieistniejące moduły lub inne błędy)

Evalds Urtans
źródło
3

Również nie ma bezpośredniego związku z OP, ale nie zrestartowanie konsoli Python PyCharm po dodaniu nowego obiektu do modułu jest również świetnym sposobem na bardzo myląceImportError: Cannot import name ...

Mylące jest to, że PyCharm automatycznie uzupełni import w konsoli, ale import nie powiedzie się.

djvg
źródło
2

Problem jest jasny: zależność cykliczna między nazwami w entityiphysics modułów.

Bez względu na import całego modułu lub tylko klasy, nazwy muszą zostać załadowane.

Zobacz ten przykład:

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

Zostanie to skompilowane w:

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

Za pomocą jednej niewielkiej zmiany możemy rozwiązać ten problem:

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

Zostanie to skompilowane w:

# 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!
DuniC
źródło
2

W moim przypadku pracowałem w notatniku Jupyter i działo się tak, ponieważ import był już buforowany, gdy zdefiniowałem klasę / funkcję w moim pliku roboczym.

Uruchomiłem ponownie jądro Jupyter i błąd zniknął.

Harry M.
źródło
1

Nie specjalnie dla tego pytającego, ale ten sam błąd pokaże, czy nazwa klasy w imporcie nie zgadza się z definicją w pliku, z którego importujesz.

Bennett
źródło