ImportError: Tidak dapat mengimpor nama X

540

Saya memiliki empat file berbeda bernama: utama, vektor, entitas dan fisika. Saya tidak akan memposting semua kode, hanya impor, karena saya pikir di situlah kesalahannya. (Jika Anda mau, saya dapat memposting lebih banyak)

Utama:

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

Kesatuan:

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

Vektor:

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

Fisika:

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

Saya kemudian lari dari main.py dan saya mendapatkan kesalahan berikut:

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

Saya sangat baru dengan Python tetapi telah bekerja dengan C ++ untuk waktu yang lama. Saya menduga bahwa kesalahan adalah karena mengimpor entitas dua kali, sekali di utama, dan kemudian dalam fisika, tapi saya tidak tahu solusinya. Adakah yang bisa membantu?

Ya Tuhan
sumber
Apa struktur direktori tempat mereka disimpan dan di mana direktori?
Ben
1
lihat jawaban ini untuk mengimpor loop dengan python: stackoverflow.com/questions/7199466/…
Gregor
Secara umum, ini bukan praktik pengkodean yang baik untuk dilakukan from <module> import <name>, atau from <modlue> import *. Lebih baik mengimpor di bawah namespace modul untuk mencegah kemungkinan menimpa referensi yang diidentifikasi secara identik.
Joel Cornett
1
@ jsells Anda hanya perlu memanggil kelas Anda Entitydan Vectorbukannya Entdan Vect, tidak ada alasan untuk mempersingkat nama tersebut. Dan ya, gunakan import vectorlalu x = vector.Vector(0,0,0).
7
Hai @Kevin karena Anda mengenal Java lebih baik, apa kesan Anda tentang artikel 2008 ini di mana kalimat pertama penulis merujuk pada bagaimana dependensi melingkar adalah "praktik yang cukup umum" di Jawa?
HeyWatchIni

Jawaban:

503

Anda memiliki impor yang bergantung pada edaran. physics.pydiimpor dari entitysebelum kelas Entdidefinisikan dan physicsmencoba untuk mengimpor entityyang sudah diinisialisasi. Hapus ketergantungan ke physicsdari entitymodul.

Teemu Ikonen
sumber
5
Tidak banyak yang dapat Anda lakukan selain memperbaiki kode Anda. Jika Anda tidak merujuk Fisika di Ent konstruktor definisi memindahkan mport tepat di bawah Ent. Jika ya, tambahkan metode seperti setPhysics untuk mengaktifkan impor setelah konstruktor.
Teemu Ikonen
12
@ jsells Karena Anda telah bekerja dengan C ++ "untuk waktu yang lama", Anda harus tahu bahwa dua kelas TIDAK PERNAH bergantung satu sama lain. Ini sangat penting dalam C ++, dan bahkan jika itu bukan hal # 1 di Python, masih merupakan ide yang sangat bagus untuk mengikuti aturan ini. Tidak pernah ada dua kelas yang saling kenal, tidak pernah. Jika Anda memerlukan bantuan untuk membuat struktur untuk kelas Anda, posting juga sisa kode. Bagaimana tepatnya (dalam hal kode) Entitydan Physicsterhubung satu sama lain? Saya yakin ada solusi untuk apa yang Anda coba lakukan.
7
@ user2032433 Itu benar-benar tergantung pada apa yang Anda maksud dengan 'kenal satu sama lain'. Memang benar bahwa desain yang baik biasanya menghasilkan pohon dependensi satu arah dan ini biasanya pendekatan terbaik. Tapi ada pengecualian untuk ini. Kelas C ++ tentu dapat merujuk satu sama lain secara sirkuler. (Meskipun tidak mungkin bagi mereka untuk terdiri dari satu sama lain.) Tanpa maju-deklarasi, ini adalah masalah dalam Python yang tidak selalu memiliki solusi C ++.
John McFarlane
93
Pernyataan "dua kelas harus TIDAK PERNAH bergantung satu sama lain" adalah sampah. Navigasi dua arah (dua arah) sangat umum dalam orientasi objek. books.google.co.uk/...
Martin Spamer
5
Pola desain negara (misalnya) biasanya diimplementasikan dengan kelas konteks dan antarmuka negara. Instances of State diteruskan instance Context sehingga mereka dapat memanggil setState. Ini mengharuskan Negara untuk mengetahui tentang Konteks dan sebaliknya. Bagaimana konstruksi klasik ini menjadi "buruk pada kode"? Sebenarnya itulah masalah yang saya geluti dengan Python, tetapi tidak harus ketika saya mengimplementasikan State di Java.
Auspice
142

Meskipun Anda harus menghindari ketergantungan melingkar, Anda dapat menunda impor dengan python.

sebagai contoh:

import SomeModule

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

ini (setidaknya dalam beberapa kasus) akan menghindari kesalahan.

membingungkan
sumber
38
dependensi melingkar sebaiknya dielakkan
ckb
4
Berdasarkan pada pep8, memasukkan metode impor ke dalam bukanlah praktik yang baik
TomSawyer
@ TomSawyer Mengapa?
Kröw
@ TomSawyer Saya tidak merekomendasikan ini, tapi ini adalah solusi cepat yang dapat membuat Anda keluar dari ikatan
memalukan
117

Ini adalah ketergantungan sirkuler. Ini dapat diselesaikan tanpa modifikasi struktural pada kode. Masalahnya terjadi karena vectorpermintaan Anda yang entitytersedia untuk digunakan segera, dan sebaliknya. Alasan untuk masalah ini adalah Anda meminta untuk mengakses konten modul sebelum siap - dengan menggunakan from x import y. Ini pada dasarnya sama dengan

import x
y = x.y
del x

Python mampu mendeteksi dependensi melingkar dan mencegah impor tak terbatas. Pada dasarnya semua yang terjadi adalah bahwa placeholder kosong dibuat untuk modul (mis. Tidak memiliki konten). Setelah modul dependen melingkar dikompilasi, ia memperbarui modul yang diimpor. Ini bekerja seperti ini.

a = module() # import a

# rest of module

a.update_contents(real_a)

Agar python dapat bekerja dengan dependensi melingkar, Anda harus menggunakan import xgaya saja.

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

Karena Anda tidak lagi merujuk pada isi modul di tingkat atas, python dapat mengkompilasi modul tanpa benar-benar harus mengakses konten ketergantungan melingkar. Yang saya maksud dengan level teratas adalah baris-baris yang akan dieksekusi selama kompilasi yang bertentangan dengan isi fungsi (mis. y = x.y). Variabel statis atau kelas yang mengakses konten modul juga akan menyebabkan masalah.

Bukit pasir
sumber
24

Untuk memperjelas logika adalah sangat penting. Masalah ini muncul, karena referensi menjadi lingkaran mati.

Jika Anda tidak ingin mengubah logika, Anda bisa meletakkan beberapa pernyataan impor yang menyebabkan ImportError ke posisi file lainnya, misalnya akhir.

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

Anda akan mendapatkan Kesalahan Impor: ImportError: cannot import name 'a1'

Tetapi jika kita mengubah posisi dari test.b impor b2 dalam A seperti di bawah ini:

a.py

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

from test.b import b2

Dan kita bisa mendapatkan apa yang kita inginkan:

b1
a1
b2
g10guang
sumber
18

Ini adalah ketergantungan sirkuler. kita bisa menyelesaikan masalah ini dengan menggunakan modul impor atau kelas atau fungsi di mana kita perlu. jika kita menggunakan pendekatan ini, kita dapat memperbaiki ketergantungan sirkuler

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
sumber
17

Saya baru saja mendapatkan kesalahan ini juga, untuk alasan yang berbeda ...

from my_sub_module import my_function

Script utama memiliki ujung garis Windows. my_sub_modulememiliki ujung garis UNIX. Mengubahnya menjadi sama memperbaiki masalah. Mereka juga harus memiliki pengkodean karakter yang sama.

marengaz
sumber
7

Seperti yang telah disebutkan, ini disebabkan oleh ketergantungan melingkar . Apa yang belum disebutkan adalah bahwa ketika Anda menggunakan modul pengetikan Python dan Anda mengimpor kelas hanya untuk digunakan untuk membubuhi keterangan Jenis , Anda dapat menggunakan referensi Teruskan :

Ketika sebuah petunjuk tipe berisi nama-nama yang belum didefinisikan, definisi tersebut dapat dinyatakan sebagai string literal, untuk diselesaikan nanti.

dan hapus dependensi ( impor ), mis. alih-alih

from my_module import Tree

def func(arg: Tree):
    # code

melakukan:

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

(perhatikan importpernyataan yang dihapus )

Tomasz Bartkowiak
sumber
6

Jangan beri nama skrip python Anda saat ini dengan nama beberapa modul lain yang Anda impor

Solusi: ganti nama skrip python Anda

Contoh:

  1. Anda bekerja di medicaltorch.py
  2. dalam skrip itu, Anda memiliki: di from medicaltorch import datasets as mt_datasetsmana medicaltorchseharusnya modul terpasang

Ini akan gagal dengan ImportError. Cukup ganti nama skrip python Anda dalam 1.

Paul
sumber
Terima kasih, ini menyelesaikan masalah yang saya miliki. Saya menggunakan pustaka colorama dan menamai file colorama.py, jadi python tidak tahu apa yang harus diimpor. Mengubah nama file membantu.
Marek Bodziony
5

Belum melihatnya di sini - ini sangat bodoh, tetapi pastikan Anda mengimpor variabel / fungsi yang benar.

Saya mendapatkan kesalahan ini

ImportError: tidak dapat mengimpor nama IMPLICIT_WAIT

karena variabel saya sebenarnya IMPLICIT_TIMEOUT.

ketika saya mengubah impor saya untuk menggunakan nama yang benar, saya tidak lagi mendapatkan kesalahan 🤦‍♂️

Nick Brady
sumber
1
Saya siap untuk membunuh seseorang yang mencoba mencari tahu mengapa from PIL import Pillowtidak berhasil. 😠
aalaap
5

Jika Anda mengimpor file1.pydari file2.pydan menggunakan ini:

if __name__ == '__main__':
    # etc

Variabel di bawah ini yang file1.py tidak dapat diimpor ke file2.pykarena __name__ tidak sama __main__ !

Jika Anda ingin mengimpor sesuatu dari file1.pyke file2.py, Anda harus menggunakan ini di file1.py:

if __name__ == 'file1':
    # etc

Jika ragu, buat assertpernyataan untuk menentukan apakah__name__=='__main__'

Nicolas Gervais
sumber
4

Salah satu cara untuk melacak kesalahan impor adalah langkah demi langkah mencoba menjalankan python pada setiap file yang diimpor untuk melacak yang buruk.

  1. Anda mendapatkan sesuatu seperti:

    python ./main.py

    ImportError: tidak dapat mengimpor nama A

  2. maka Anda meluncurkan:

    python ./modules/a.py

    ImportError: tidak dapat mengimpor nama B

  3. maka Anda meluncurkan:

    python ./modules/b.py

    ImportError: tidak dapat mengimpor nama C (modul NON-Ada atau beberapa kesalahan lain)

Evalds Urtans
sumber
3

Juga tidak secara langsung relevan dengan OP, tetapi gagal untuk me - restart konsol PyCharm Python, setelah menambahkan objek baru ke modul, juga merupakan cara yang bagus untuk mendapatkan yang sangat membingungkanImportError: Cannot import name ...

Bagian yang membingungkan adalah PyCharm itu akan melengkapi impor secara otomatis di konsol, tetapi impor tersebut kemudian gagal.

djvg
sumber
2

Masalahnya jelas: ketergantungan melingkar antara nama di entitydanphysics modul.

Terlepas dari mengimpor seluruh modul atau hanya kelas, nama harus dimuat.

Tonton contoh ini:

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

Ini akan dikompilasi menjadi:

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

Dengan satu perubahan kecil kita dapat menyelesaikan ini:

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

Ini akan dikompilasi menjadi:

# 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
sumber
2

Dalam kasus saya, saya bekerja di notebook Jupyter dan ini terjadi karena impor sudah di-cache sejak saya mendefinisikan kelas / fungsi di dalam file kerja saya.

Saya memulai kembali kernel Jupyter saya dan kesalahannya hilang.

Harry M.
sumber
1

Tidak khusus untuk penanya ini, tetapi kesalahan yang sama ini akan muncul jika nama kelas dalam impor Anda tidak cocok dengan definisi dalam file yang Anda impor.

Bennett
sumber