Apa kesalahan angka sulap buruk?

320

Apa itu ImportError "Bad magic number" dengan python, dan bagaimana cara memperbaikinya?

Satu-satunya hal yang dapat saya temukan secara online menunjukkan bahwa ini disebabkan oleh kompilasi file .py -> .pyc dan kemudian mencoba menggunakannya dengan versi python yang salah. Namun, dalam kasus saya, file tersebut sepertinya mengimpor dengan baik beberapa kali tetapi tidak yang lain, dan saya tidak yakin mengapa.

Pemberian informasi python dalam traceback tidak terlalu membantu (itulah sebabnya saya bertanya di sini ...), tapi di sini kalau-kalau itu membantu:

Traceback (most recent call last):
  File "run.py", line 7, in <module>
    from Normalization import Normalizer
Nuh
sumber
Bisakah Anda memberikan kode di mana masalah terjadi?
Evan Fosmark
Dan versi python mana yang Anda gunakan?
paxdiablo
Dan apakah Normalisasi adalah salah satu file Anda atau pihak ketiga?
paxdiablo
3
Hrm, oke, saya pikir saya pasti telah mengimpor file .pyc lama yang sudah lama ditinggalkan ketika saya memindahkan file .py, jadi saya bisa mengimpor versi baru tetapi tidak yang lama.
Noah
1
Saya memotong file .pyc yang lama, jadi saya tidak memiliki itu berguna, tetapi masalah saya adalah dengan jalur impor - saya pikir python akan menggunakan file .py untuk membuat kembali file .pyc jika saya tidak memindahkannya (benarkah itu?)
Noah

Jawaban:

401

Nomor ajaib berasal dari sistem tipe UNIX di mana beberapa byte pertama dari sebuah file memegang penanda yang menunjukkan jenis file.

Python menempatkan penanda serupa ke dalam pycfile -nya ketika itu menciptakan mereka.

Kemudian interpreter python memastikan angka ini benar ketika memuatnya.

Apa pun yang merusak angka ajaib ini akan menyebabkan masalah Anda. Ini termasuk mengedit pycfile atau mencoba menjalankan pycdari versi python yang berbeda (biasanya lebih baru) dari penerjemah Anda.

Jika itu adalah file Anda pyc , hapus saja dan biarkan penerjemah mengkompilasi ulang pyfile. Pada sistem tipe UNIX, itu bisa menjadi sesuatu yang sederhana seperti:

rm *.pyc

atau:

find . -name '*.pyc' -delete

Jika bukan milik Anda, Anda harus mendapatkan pyfile untuk kompilasi ulang, atau penerjemah yang dapat menjalankan pycfile dengan nilai ajaib tertentu.

Satu hal yang mungkin menyebabkan sifatnya terputus-putus. Yang pycmenyebabkan masalah hanya dapat diimpor dalam kondisi tertentu. Sangat tidak mungkin kadang-kadang mengimpor. Anda harus memeriksa jejak tumpukan penuh yang sebenarnya ketika impor gagal?

Sebagai tambahan, kata pertama dari semua 2.5.1(r251:54863) pycfile saya adalah 62131, 2.6.1(r261:67517)adalah 62161. Daftar semua angka ajaib dapat ditemukan di Python/import.c, direproduksi di sini untuk kelengkapan (saat ini pada saat jawaban diposting, mungkin telah berubah sejak saat itu):

1.5:   20121
1.5.1: 20121
1.5.2: 20121
1.6:   50428
2.0:   50823
2.0.1: 50823
2.1:   60202
2.1.1: 60202
2.1.2: 60202
2.2:   60717
2.3a0: 62011
2.3a0: 62021
2.3a0: 62011
2.4a0: 62041
2.4a3: 62051
2.4b1: 62061
2.5a0: 62071
2.5a0: 62081
2.5a0: 62091
2.5a0: 62092
2.5b3: 62101
2.5b3: 62111
2.5c1: 62121
2.5c2: 62131
2.6a0: 62151
2.6a1: 62161
2.7a0: 62171
paxdiablo
sumber
2
Terima kasih - ini tidak secara langsung membantu saya memecahkan masalah saya, tetapi senang mengetahui jawabannya!
Noah
Bagaimana saya bisa memeriksa file pyc apa yang menyebabkan masalah, saya telah menghapus semua file pyc tetapi masih mendapatkan kesalahan ini.
sunprophit
Mungkin Anda perlu 'rm __pycache __ / * pyc' sekarang, karena file-file pyc sekarang ada di folder itu.
Arpad Horvath
1
Terima kasih! Itu terjadi pada saya dengan: ERROR: tornado.general: Tidak dapat memuat terjemahan untuk 'es': [Errno 0] Angka ajaib buruk: '/app/locale/es/LC_MESSAGES/django.mo'. Sebenarnya, * .mo tidak dikompilasi dengan benar.
ericson.cepeda
1
Daftar lebih lengkap di sini: github.com/google/pytype/blob/master/pytype/pyc/magic.py
Davy
60

Menghapus semua file .pyc akan memperbaiki kesalahan "Bad Magic Number".

find . -name "*.pyc" -delete
akarca
sumber
8
Mungkin lebih baik untuk digunakan find . -name "*.pyc" -delete, karena Anda akan memiliki masalah dengan spasi (dan mungkin dengan terlalu lama baris perintah) jika Anda memperluas semua nama file untuk dilewati rm.
Andrew Aylett
25
IMO itu skrip yang cukup berbahaya. Bagaimana jika sebuah paket dikirimkan hanya dengan file .pyc agar tetap tertutup? Ups, Anda baru saja menghapus aplikasi.
Dan Mantyla
3
Mungkin yang terbaik untuk menjalankan pertama find . -name "*.pyc" -printdan hanya kemudian menghapus file yang bermasalah secara manual, dan / atau menjalankan perintah di atas, setelah memverifikasi Anda tidak melakukan sesuatu yang disesalkan.
michael
9
@DanMantyla Paket sumber tertutup layak dihapus.
kucing
25

Memuat *.pycfile yang dihasilkan python3 dengan python2 juga menyebabkan kesalahan ini.

jtm
sumber
3
Ini bisa berupa komentar, bukan jawaban.
Kroltan
2
@ Kroltan namun itu sangat bagus sebagai jawaban, lebih baik daripada yang diterima. Ringkas dan to-the-point.
Antony Hatchkins
@AntonyHatchkins Setidaknya dalam pandangan saya, ini bisa menjadi komentar pada salah satu jawaban yang menyarankan penghapusan .pyc. Meskipun ini adalah salah satu penyebab yang mungkin , itu tidak memiliki solusi yang berbeda , jadi ini berlebihan. Jangan ragu untuk tidak setuju, hanya pendapat saya.
Kroltan
@Kroltan Bagian 'cara memperbaiki' cukup jelas di sini. Penyebabnya, itulah yang benar-benar menarik - setidaknya bagi saya - adalah. Saya melakukan banyak mangling dengan versi python 2.x yang berbeda dan tidak pernah menemukan ketidakcocokan antara versi .pyc. Dan solusi ini mengatakan itu adalah masalah python3 vs python2 - informasi hilang dalam jawaban yang diterima. Plus, saya suka jawaban singkat (jika mungkin) :)
Antony Hatchkins
@AntonyHatchkins, solusi ini mungkin mengatakan itu masalah py2 / 3 tapi itu hanya satu kemungkinan dan, dalam hal ini, satu yang disarankan dalam jawaban yang diterima (paragraf 4) sejak versi pertamanya :-)
paxdiablo
6

Bawa file pyc ke mesin windows. Gunakan Hex editor untuk membuka file pyc ini. Saya menggunakan freeware 'HexEdit'. Sekarang baca nilai hex dua byte pertama. Dalam kasus saya, ini adalah 03 f3.

Buka calc dan ubah mode tampilan ke Programmer (Scientific in XP) untuk melihat Hex dan konversi Desimal. Pilih "Hex" dari tombol Radio. Masukkan nilai sebagai byte kedua pertama dan kemudian byte pertama yaitu f303 Sekarang klik pada tombol radio "Des" (Desimal). Nilai yang ditampilkan adalah yang sesuai dengan angka ajaib alias versi python.

Jadi, mengingat tabel yang disediakan di balasan sebelumnya

  • 1.5 => 20121 => 4E99 sehingga file memiliki byte pertama sebagai 99 dan kedua sebagai 4e
  • 1.6 => 50428 => C4FC sehingga file memiliki byte pertama sebagai fc dan kedua sebagai c4
Sanjay Chopra
sumber
2

Kesalahan "Angka ajaib buruk" juga terjadi jika Anda secara manual memberi nama file Anda dengan ekstensi .pyc

Deke
sumber
1

Saya memiliki kasus aneh kesalahan Bad Magic Number menggunakan implementasi yang sangat lama (1.5.2). Saya menghasilkan file .pyo dan itu memicu kesalahan. Anehnya, masalah diselesaikan dengan mengubah nama modul. Nama yang menyinggung adalah sms.py. Jika saya menghasilkan sms.pyo dari modul itu, kesalahan Bad Magic Number adalah hasilnya. Ketika saya mengubah nama menjadi smst.py, kesalahan hilang. Saya memeriksa bolak-balik untuk melihat apakah sms.py entah bagaimana mengganggu modul lain dengan nama yang sama tetapi saya tidak dapat menemukan tabrakan nama. Meskipun sumber masalah ini tetap menjadi misteri bagi saya, saya sarankan mencoba perubahan nama modul.

Gábor Paller
sumber
1

Ini juga bisa disebabkan oleh __init__.pyfile yang hilang dari direktori. Katakanlah jika Anda membuat direktori baru di Django untuk memisahkan tes unit menjadi beberapa file dan menempatkannya dalam satu direktori maka Anda juga harus membuat __init__.pyfile di samping semua file lain di direktori tes yang baru dibuat. selain itu bisa memberikan error seperti Traceback (most recent call last): File "C:\Users\USERNAME\AppData\Local\Programs\Python\Python35\Lib\unittest\loader.py",line 153, in loadTestsFromName module = __import__(module_name) ImportError: bad magic number in 'APPNAME.tests': b'\x03\xf3\r\n'

Shahraiz Ali
sumber
0

Ini jauh lebih efisien daripada di atas.

find {directory-of-.pyc-files} -name "*.pyc" -print0 | xargs -0 rm -rf

di mana {directory-of-.pyc-files}direktori yang berisi file python yang dikompilasi.

ozgurv
sumber
1
Itu kalau-kalau Anda memiliki file py di tangan, jika tidak, Anda akan perlu downgrade instalasi python.
Leon Fedotov
1
Ini masih tidak aman untuk beberapa kasus tepi. Juga mengapa kita melakukan penghapusan rekursif ketika kita berbicara tentang file?
Jerome Baum
1
Mengapa Anda menggunakan dua proses? Meskipun ditemukan tidak terhapus, Anda masih dapat menjalankanfind /dir -name "*.pyc" -exec rm '{}' ';'
mikemaccana
1
Perintah 'find' tidak akan bekerja dengan aman untuk nama file dengan spasi di jika operator final -print default digunakan secara langsung oleh xargs rm. Python tidak mengimpor file bernama non-pengenal seperti ini, tetapi skrip masih dapat menyebabkan ini rusak dan mereka tidak akan dihapus. Umumnya selalu lebih aman untuk menggunakan ekstra-print0 (nol di ujung) pada perintah find (sebagai parameter terakhir sebelum simbol pipa '|') dan kemudian opsi -0 pada xargs (itu tanda hubung + nol) untuk memahami - print0 output sebelum perintah rm, ketika piping menemukan ke xargs.
Breezer
0

Dalam kasus saya itu bukan file terjemahan .pycbiner lama .mosetelah saya mengganti nama modul saya sendiri, jadi di dalam folder modul ini saya harus menjalankan

find . -name \*.po -execdir sh -c 'msgfmt "$0" -o `basename $0 .po`.mo' '{}' \;

(tolong lakukan backup dan coba perbaiki .pycfile terlebih dahulu)

d9k
sumber
0

Ini juga dapat terjadi jika Anda memiliki file python27.dll yang salah (untuk Windows), untuk menyelesaikan ini instal ulang (atau ekstrak) python dengan versi dll yang sesuai. Saya memiliki pengalaman serupa.

Ibrahim
sumber
0

Saya baru saja menghadapi masalah yang sama dengan Fedora26 di mana banyak alat seperti dnf rusak karena angka sihir buruk selama enam. Untuk alasan yang tidak diketahui saya punya file /usr/bin/six.pyc, dengan nomor ajaib yang tidak terduga. Menghapus file ini memperbaiki masalahnya

zedge
sumber
0

Dalam kasus saya, saya punya git clonelib yang memiliki juru bahasa

#!/usr/bin/env python

Sementara pythonitu mengarah ke Python2.7meskipun kode utama saya berjalan dengan python3.6 ... itu masih membuat *.pycfile untuk 2.7versi ...

Saya dapat mengatakan bahwa kesalahan ini mungkin merupakan hasil dari perpaduan antara versi 2.7 & 3+, inilah mengapa pembersihan (dengan cara apa pun yang Anda pikirkan tentang yang Anda gunakan) - akan membantu di sini ...

  • jangan lupa untuk menyesuaikan kode Python2x -> python 3 ...
Ricky Levi
sumber
-1

Jangan hapus mereka !!! Sampai..........

Temukan versi di git, svn atau salin folder yang berfungsi.

Hapus mereka dan pulihkan semua .pyc.

Itu bekerja untuk saya.

lauralacarra
sumber
eyyy mengapa saya punya -1? itu benar-benar bekerja untuk saya dan saya berada dalam situasi yang sangat buruk ¬¬
lauralacarra
2
kembali ke versi sebelumnya bukan solusi global
ZiTAL
4
Mengapa Anda melakukan *.pycfile Anda ?
Manos Kounelakis
Itu kesalahan yang biasa. Ketika Anda tidak mengkonfigurasi git, abaikan file dengan benar. Jadi saya memberikan solusinya dan kemudian Anda harus memesan git Anda.
lauralacarra
-1

Anda perlu menjalankan perintah ini di setiap jalur yang Anda miliki di lingkungan Anda.

>>> import sys
>>> sys.path
['', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/usr/local/lib/python3.6/dist-packages', '/source_code/src/python', '/usr/lib/python3/dist-packages']

Kemudian jalankan perintah di setiap direktori di sini

find /usr/lib/python3.6/ -name "*.pyc" -delete
find /usr/local/lib/python3.6/dist-packages -name "*.pyc" -delete
# etc...
Ahmed
sumber