Jaki jest błąd złej magicznej liczby?

320

Co to jest błąd importu „Zła liczba magiczna” w pythonie i jak go naprawić?

Jedyne, co mogę znaleźć online, sugeruje, że jest to spowodowane kompilacją pliku .py -> .pyc, a następnie próbą użycia go z niewłaściwą wersją Pythona. Jednak w moim przypadku plik wydaje się importować w niektórych przypadkach dobrze, ale nie w innych, i nie jestem pewien, dlaczego.

Informacje podawane przez python w śledzeniu nie są szczególnie pomocne (dlatego pytałem tutaj ...), ale tutaj jest na wypadek, gdyby to pomogło:

Traceback (most recent call last):
  File "run.py", line 7, in <module>
    from Normalization import Normalizer
Noah
źródło
Czy możesz podać kod, w którym występuje problem?
Evan Fosmark,
A jakiej wersji Pythona używasz?
paxdiablo
I czy normalizacja jest jednym z twoich plików, czy też pliku innej firmy?
paxdiablo
3
Hmm, okej, myślę, że musiałem importować stary plik .pyc, który został pozostawiony dawno temu, kiedy przenosiłem plik .py, więc mogłem importować nową wersję, ale nie starą.
Noah
1
Zestartowałem stary plik .pyc, więc nie mam go pod ręką, ale mój problem dotyczył ścieżek importowania - myślę, że python użyłby pliku .py do odtworzenia pliku .pyc, gdybym go nie przeniósł (czy to prawda?)
Noah

Odpowiedzi:

400

Magiczna liczba pochodzi z systemów typu UNIX, w których kilka pierwszych bajtów pliku zawierało znacznik wskazujący typ pliku.

Python umieszcza podobny znacznik w swoich pycplikach podczas ich tworzenia.

Następnie interpreter Pythona upewnia się, że ten numer jest poprawny podczas ładowania.

Wszystko, co uszkodzi tę magiczną liczbę, spowoduje twój problem. Obejmuje to edycję pycpliku lub próbę uruchomieniapyc innej wersji Pythona (zwykle późniejszej) niż interpreter.

Jeśli są to twoje pyc pliki, po prostu je usuń i pozwól tłumaczowi ponownie skompilować pypliki. W systemach typu UNIX może to być coś tak prostego jak:

rm *.pyc

lub:

find . -name '*.pyc' -delete

Jeśli nie są twoje, będziesz musiał albo pobrać pypliki do ponownej kompilacji, albo interpreter, który będzie mógł uruchamiać pycpliki o tej konkretnej magicznej wartości.

Jedna rzecz, która może powodować przerywaną naturę. Przyczynę pycproblemu można zaimportować tylko pod pewnymi warunkami. Jest bardzo mało prawdopodobne, że czasami importuje. Powinieneś sprawdzić rzeczywisty ślad pełnego stosu, gdy import się nie powiedzie?

Tak na marginesie, to pierwsze słowo z wszystkich moich 2.5.1(r251:54863) pycplików jest 62131, 2.6.1(r261:67517)jest 62161. Lista wszystkich magicznych liczb znajduje się Python/import.ctutaj, odtworzona tutaj dla kompletności (aktualna w chwili opublikowania odpowiedzi, mogła ulec zmianie od tego czasu):

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
źródło
2
Dzięki - to nie pomogło mi bezpośrednio rozwiązać problemu, ale i tak miło jest poznać odpowiedź!
Noah
Jak mogę sprawdzić, który plik pyc powoduje problem, usunąłem wszystkie pliki pyc, ale nadal pojawia się ten błąd.
sunprophit
Być może potrzebujesz teraz „rm __pycache __ / * pyc”, ponieważ pliki pyc znajdują się teraz w tym folderze.
Arpad Horvath
1
Dzięki! Przydarzyło mi się to z: BŁĄD: tornado.general: Nie można załadować tłumaczenia dla „es”: [Errno 0] Zła magiczna liczba: '/app/locale/es/LC_MESSAGES/django.mo'. W rzeczywistości było to, że * .mo nie został poprawnie skompilowany.
ericson.cepeda
1
Bardziej obszerna lista tutaj: github.com/google/pytype/blob/master/pytype/pyc/magic.py
Davy,
60

Usunięcie wszystkich plików .pyc naprawi błąd „Bad Magic Number”.

find . -name "*.pyc" -delete
akarca
źródło
8
Prawdopodobnie lepiej go użyć find . -name "*.pyc" -delete, ponieważ będziesz mieć problemy ze spacjami (i być może ze zbyt długą linią poleceń), jeśli rozszerzysz wszystkie nazwy plików do przekazania rm.
Andrew Aylett,
25
IMO to dość niebezpieczny skrypt. Co się stanie, jeśli pakiet zostanie dostarczony tylko z plikami .pyc, aby zachować zamknięte źródło? Ups, właśnie usunąłeś aplikację.
Dan Mantyla,
3
Prawdopodobnie najlepiej najpierw uruchomić, find . -name "*.pyc" -printa dopiero potem ręcznie usunąć problematyczne pliki i / lub uruchomić powyższe polecenie, po upewnieniu się, że nie robisz czegoś godnego pożałowania.
Michael
9
@DanMantyla Zamknięte pakiety źródłowe i tak zasługują na usunięcie.
kot
25

Ładowanie *.pycpliku wygenerowanego przez python3 za pomocą python2 również powoduje ten błąd.

jtm
źródło
3
To może być komentarz, a nie odpowiedź.
Kroltan
2
@Kroltan jest jeszcze cholernie dobra jako odpowiedź, lepsza niż przyjęta. Zwięzłe i na temat.
Antony Hatchkins
@AntonyHatchkins Przynajmniej moim zdaniem może to być komentarz do dowolnej odpowiedzi sugerującej usunięcie pliku .pyc. Chociaż jest to jedna z możliwych przyczyn , nie ma innego rozwiązania , więc jest to zbędne. Nie zgadzam się, tylko moja opinia.
Kroltan
@Kroltan Część „jak naprawić” jest tutaj dość oczywista. Przyczyną jest to, co naprawdę interesujące - przynajmniej dla mnie -. Robiłem dużo manipulacji z różnymi wersjami Pythona 2.x i nigdy nie spotkałem żadnych niezgodności między wersjami .pyc. I to rozwiązanie mówi, że jest to problem python3 vs python2 - brak informacji w zaakceptowanej odpowiedzi. Dodatkowo uwielbiam krótkie odpowiedzi (tam, gdzie to możliwe) :)
Antony Hatchkins
@AntonyHatchkins, to rozwiązanie może powiedzieć, że jest to problem z py2 / 3, ale to tylko jedna możliwość i, w tym przypadku, jedna zasugerowana w zaakceptowanej odpowiedzi (akapit 4) od jej pierwszej wersji :-)
paxdiablo
6

Zabierz plik pyc do komputera z systemem Windows. Użyj dowolnego edytora szesnastkowego, aby otworzyć ten plik pyc. Użyłem freeware „HexEdit”. Teraz odczytaj wartość szesnastkową pierwszych dwóch bajtów. W moim przypadku były to 03 f3.

Otwórz calc i przekonwertuj jego tryb wyświetlania na Programmer (Scientific w XP), aby zobaczyć konwersję szesnastkową i dziesiętną. Wybierz „Hex” z przycisku Radio. Wprowadź najpierw wartości jako drugi bajt, a następnie pierwszy bajt, tj. F303 Teraz kliknij przycisk radiowy „Dec” (dziesiętny). Wyświetlana wartość to taka, która odpowiada magicznej liczbie, czyli wersji Pythona.

Biorąc pod uwagę tabelę zawartą we wcześniejszej odpowiedzi

  • 1.5 => 20121 => 4E99, więc pliki miałyby pierwszy bajt jako 99, a drugi jako 4e
  • 1.6 => 50428 => C4FC, więc pliki miałyby pierwszy bajt jako fc, a drugi jako c4
Sanjay Chopra
źródło
2

Błąd „zły numer magiczny” występuje również, jeśli plik został ręcznie nazwany rozszerzeniem .pyc

Deke
źródło
1

Miałem dziwny przypadek błędu Bad Magic Number przy użyciu bardzo starej implementacji (1.5.2). Wygenerowałem plik .pyo, co spowodowało błąd. Dziwnie, problem został rozwiązany przez zmianę nazwy modułu. Obraźliwa nazwa to sms.py. Jeśli wygenerowałem sms.pyo z tego modułu, błąd Bad Magic Number był wynikiem. Kiedy zmieniłem nazwę na smst.py, błąd zniknął. Sprawdzałem tam i z powrotem, czy sms.py w jakiś sposób koliduje z jakimkolwiek innym modułem o tej samej nazwie, ale nie mogłem znaleźć kolizji nazw. Mimo że źródło tego problemu pozostało dla mnie tajemnicą, zalecam próbę zmiany nazwy modułu.

Gábor Paller
źródło
1

Może to być również spowodowane brakiem __init__.pypliku w katalogu. Powiedzmy, że jeśli utworzysz nowy katalog w django do rozdzielenia testów jednostkowych na wiele plików i umieścisz je w jednym katalogu, to musisz także utworzyć __init__.pyplik obok wszystkich innych plików w nowo utworzonym katalogu testowym. w przeciwnym razie może dać błąd jak 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
źródło
0

Jest to o wiele bardziej skuteczne niż powyżej.

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

gdzie {directory-of-.pyc-files}jest katalog zawierający skompilowane pliki Pythona.

ozgurv
źródło
1
Tak jest w przypadku, gdy masz pod ręką pliki py, jeśli nie, będziesz musiał obniżyć instalację Pythona.
Leon Fedotov
1
Jest to nadal niebezpieczne w niektórych przypadkach skrajnych. Dlaczego robimy rekurencyjne usuwanie, gdy mówimy o plikach?
Jerome Baum
1
Dlaczego korzystasz z dwóch procesów? Nawet jeśli find nie został usunięty, nadal możesz uruchomićfind /dir -name "*.pyc" -exec rm '{}' ';'
mikemaccana,
1
Polecenie „znajdź” nie będzie działało bezpiecznie dla nazw plików ze spacjami, jeśli domyślny operator końcowy -print jest używany bezpośrednio przez xargs rm. Python nie importuje plików o takich nazwach, które nie są identyfikatorami, ale skrypty mogą nadal powodować awarie i nie zostaną usunięte. Zasadniczo zawsze bezpieczniej jest użyć dodatkowego -print0 (zero na końcu) w poleceniu find (jako ostatni parametr przed symbolem potoku „|”), a następnie opcji -0 na xargs (to znaczy łącznik + zero), aby zrozumieć - wypisz 0 na wyjście przed poleceniem rm, gdy potokujesz find w xargs.
Breezer
0

W moim przypadku nie były to .pycstare .mopliki tłumaczeń binarnych po zmianie nazwy własnego modułu, więc w tym folderze modułu musiałem uruchomić

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

(wykonaj kopię zapasową i spróbuj .pycnajpierw naprawić pliki)

d9k
źródło
0

Może się to również zdarzyć, jeśli masz niewłaściwy plik python27.dll (w przypadku systemu Windows), aby rozwiązać ten problem, po prostu zainstaluj ponownie (lub rozpakuj) python z dokładnie odpowiednią wersją dll. Miałem podobne doświadczenie.

Ibrahim.H
źródło
0

Właśnie spotkałem ten sam problem z Fedorą 26, w której wiele narzędzi, takich jak dnf, zostało uszkodzonych z powodu złej liczby magicznej dla sześciu. Z nieznanego powodu mam plik /usr/bin/six.pyc z nieoczekiwaną magiczną liczbą. Usunięcie tego pliku rozwiązuje problem

zedge
źródło
0

W moim przypadku mam git clonelib, który miał tłumacza

#!/usr/bin/env python

Chociaż pythonprowadziło to do Python2.7tego, że mój główny kod działał z python3.6 ... nadal tworzył *.pycplik dla 2.7wersji ...

Mogę powiedzieć, że ten błąd prawdopodobnie jest wynikiem pomieszania między wersjami 2.7 i 3+, dlatego właśnie czyszczenie (w dowolny sposób możesz myśleć o tym, że używasz) - pomoże tutaj ...

  • nie zapomnij dostosować tych kodów Python2x -> python 3 ...
Ricky Levi
źródło
-1

Nie usuwaj ich !!! Aż do..........

Znajdź wersję swojego folderu git, svn lub kopiowania, która działa.

Usuń je, a następnie odzyskaj wszystkie pliki .pyc.

To dla mnie praca.

lauralacarra
źródło
Ej, dlaczego mam -1? to naprawdę działa dla mnie i byłem w naprawdę złej sytuacji ¬¬
lauralacarra
2
powrót do poprzedniej wersji nie jest rozwiązaniem globalnym
ZiTAL
4
Dlaczego miałbyś kiedykolwiek zatwierdzać swoje *.pycpliki?
Manos Kounelakis,
To jest zwykły błąd. Jeśli nie skonfigurujesz poprawnie pliku git, zignoruj ​​go. Więc podaję rozwiązanie, a potem musisz zamówić swojego gita.
lauralacarra
-1

Musisz uruchomić to polecenie na każdej ścieżce w swoim środowisku.

>>> 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']

Następnie uruchom polecenie w każdym katalogu tutaj

find /usr/lib/python3.6/ -name "*.pyc" -delete
find /usr/local/lib/python3.6/dist-packages -name "*.pyc" -delete
# etc...
Ahmed
źródło