Яка погана помилка магічного числа?


320

Що таке "Bad Magical Number" ImportError у python, і як це виправити?

Єдине, що я можу знайти в Інтернеті, це спричинити, якщо скомпілювати файл .py -> .pyc і потім спробувати використовувати його з неправильною версією python. У моєму випадку, однак, файл іноді добре імпортує, але не інші, і я не знаю, чому.

Забезпечення інформаційного пітону у прослідкуванні не особливо корисне (саме тому я тут просив ...), але ось у випадку, якщо це допомагає:

Traceback (most recent call last):
  File "run.py", line 7, in <module>
    from Normalization import Normalizer

Чи можете ви надати код, у якому виникає проблема?
Еван Фосмарк

І яку версію python ви використовуєте?
paxdiablo

І чи нормалізація є одним із ваших файлів чи стороннім?
paxdiablo

3
Хрм, гаразд, я думаю, що, мабуть, я імпортував старий файл .pyc, який залишився давно, коли я перемістив файл .py, і тому я міг імпортувати нову версію, але не стару.
Ной

1
Я застосував старий файл .pyc, тому мені це не зручно, але моя проблема полягала в шляхах імпорту - я думаю, що python використовував би файл .py для відтворення файлу .pyc, якби я не перемістив його (це правильно?)
Ной

Відповіді:


400

Магічне число походить від систем UNIX-типу, де перші кілька байтів файлу містили маркер із зазначенням типу файлу.

Python ставить подібний маркер у свої pycфайли під час їх створення.

Тоді інтерпретатор python переконує, що це число правильне при завантаженні.

Все, що пошкодить це магічне число, спричинить вашу проблему. Сюди входить редагування pycфайлу або спроба запускуpyc з іншої версії python (зазвичай пізніше), ніж ваш інтерпретатор.

Якщо це ваші pyc файли, просто видаліть їх і дозвольте перекладачеві перекомпілювати pyфайли. У системах типу UNIX це може бути настільки просто, як:

rm *.pyc

або:

find . -name '*.pyc' -delete

Якщо вони не є вашими, вам доведеться або отримати pyфайли для повторної компіляції, або інтерпретатор, який може запускати pycфайли саме з цим магічним значенням.

Одне, що може викликати переривчастий характер. Це pycє причиною проблеми, яку можна імпортувати лише за певних умов. Це малоймовірно, що воно іноді імпортуватиме. Ви повинні перевірити фактичний повний слід стека, коли імпорт не вдається?

Як і в сторону, то перше слово з усіх моїх 2.5.1(r251:54863) pycфайлів 62131, 2.6.1(r261:67517)є 62161. Список усіх магічних чисел можна знайти Python/import.c, відтворений тут для повноти (поточний, як на момент опублікування відповіді, можливо, з тих пір змінився):

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

2
Дякую - це не допомогло мені прямо з'ясувати мою проблему, але приємно знати відповідь у будь-якому випадку!
Ной

Як я можу перевірити, який файл pyc викликає проблему, я видалив усі файли pyc, але все ж отримую цю помилку.
sunprophit

Можливо, вам зараз потрібен 'rm __pycache __ / * pyc', оскільки файли pyc зараз знаходяться в цій папці.
Арпад Хорват

1
Дякую! Зі мною траплялося: ПОМИЛКА: tornado.general: Неможливо завантажити переклад для 'es': [Errno 0] Неправильний магічний номер: '/app/locale/es/LC_MESSAGES/django.mo'. Фактично, * .mo було складено неправильно.
ericson.cepeda

1
Більш детальний список тут: github.com/google/pytype/blob/master/pytype/pyc/magic.py
Дейві

60

Видалення всіх файлів .pyc виправить помилку "Bad Magic Number".

find . -name "*.pyc" -delete

8
Це, мабуть, краще використовувати find . -name "*.pyc" -delete, оскільки у вас виникнуть проблеми з пробілами (і, можливо, із занадто довгим командним рядком), якщо ви розгорнете всі назви файлів для передачі rm.
Ендрю Ейлетт

25
IMO - це досить небезпечний сценарій. Що робити, якщо пакет був доставлений лише з .pyc файлами, щоб зберегти його закритим джерелом? На жаль, ви просто видалили програму.
Dan Mantyla

3
Напевно, найкраще спочатку запустити find . -name "*.pyc" -printі лише потім видалити проблемні файли вручну та / або виконати команду вище, перевіривши, що ви не робите чогось жалючого.
Майкл

9
@DanMantyla Закриті вихідні пакети все одно заслуговують на видалення.
кіт

25

Завантаження файлу, згенерованого python3 за *.pycдопомогою python2, також викликає цю помилку.


3
Це може бути коментар, а не відповідь.
Кролтан

2
@Kroltan все ж це проклято добре, як відповідь, краща за прийняту. Лаконічні та точні.
Ентоні Хеткінс

@AntonyHatchkins Принаймні, на мій погляд, це може бути коментарем до будь-якої відповіді, що передбачає вилучення .pyc. Незважаючи на те, що це одна з можливих причин , воно не має іншого рішення , тож це зайве. Не соромтеся, лише моя думка.
Кролтан

@Kroltan Частина "як виправити" тут досить очевидна. Причина, ось у чому насправді цікаво - принаймні для мене. Я багато вправлявся з різними версіями python 2.x і жодного разу не стикався з несумісністю між .pyc версіями. І це рішення говорить, що це проблема python3 vs python2 - інформація відсутня у прийнятій відповіді. Плюс я люблю короткі відповіді (де це можливо) :)
Ентоні Хетчкінс

@AntonyHatchkins, це рішення може сказати, що це питання py2 / 3, але це лише одна можливість, і, з цього приводу, одна запропонована у прийнятій відповіді (параграф 4) з моменту її першої версії :-)
paxdiablo

6

Перенесіть файл pyc на машину Windows. Використовуйте будь-який шестигранний редактор, щоб відкрити цей файл pyc. Я використовував безкоштовну програму "HexEdit". Тепер прочитайте шістнадцяткове значення перших двох байтів. У моєму випадку це було 03 f3.

Відкрийте calc та перетворіть його режим відображення в програміст (Scientific в XP), щоб побачити шестинадцяткове та десяткове перетворення. Виберіть "Шістнадцятковий" з перемикача. Введіть значення як перший байт, а потім перший байт, тобто f303 Тепер натисніть перемикач "Dec" (Десяткові). Виведене значення - це те, яке відповідає магічному номеру aka версії python.

Отже, розглядаючи таблицю, подану в попередній відповіді

  • 1.5 => 20121 => 4E99, тому файли мали б перший байт як 99, а другий як 4e
  • 1.6 => 50428 => C4FC, тому файли мали б перший байт як fc, а другий як c4

2

Помилка "поганого магічного номера" також виникає, якщо ви вручну назвали свій файл із розширенням .pyc


1

У мене був дивний випадок помилки «Магічне число», використовуючи дуже стару (1.5.2) реалізацію. Я створив файл .pyo, і це викликало помилку. Як не дивно, проблема була вирішена шляхом зміни назви модуля. Злочинним ім'ям було sms.py. Якщо я згенерував sms.pyo з цього модуля, в результаті з'явилася помилка «Магічне число». Коли я змінив ім'я на smst.py, помилка пішла. Я перевіряв туди і назад, щоб побачити, чи sms.py якось втручався в будь-який інший модуль з такою ж назвою, але не вдалося знайти жодного зіткнення імені. Незважаючи на те, що джерело цієї проблеми для мене залишилося загадкою, я рекомендую спробувати змінити назву модуля.


1

Це також може бути пов’язано з відсутнім __init__.pyфайлом з каталогу. Скажімо, якщо ви створили новий каталог у django для розділення тестів одиниці на декілька файлів і помістіть їх в один каталог, тоді вам також доведеться створити __init__.pyфайл поруч з усіма іншими файлами в новому створеному тестовому каталозі. інакше це може призвести до помилок 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'


0

Це набагато ефективніше, ніж вище.

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

де {directory-of-.pyc-files}каталог, який містить складені файли python.


1
Тобто, якщо у вас є файли py під рукою, якщо ні, вам не потрібно буде знизити встановлення python.
Леон Федотов

1
Це все ще небезпечно для деяких крайових випадків. Також чому ми робимо рекурсивне видалення, коли ми говоримо про файли?
Джером Баум

1
Чому ви використовуєте два процеси? Навіть якщо у видаленні не було видалення, ви все одно можете запуститиfind /dir -name "*.pyc" -exec rm '{}' ';'
mikemaccana

1
Команда 'find' не працюватиме безпечно для імен файлів з пробілами, якщо кінцевий оператор -принт за замовчуванням використовується безпосередньо xargs rm. Python не імпортує такі файли з ім’ям, що не мають ідентифікатора, але сценарії все-таки можуть призвести до цього порушення, і вони не будуть видалені. Зазвичай завжди безпечніше використовувати додатковий -print0 (нульовий кінець) у команді find (як останній параметр перед символом труби '|'), а потім -0 на xargs (це дефіс + нуль) для розуміння - Вивести print0 перед командою rm, коли трубопровід знайдіть у xargs.
Бриззер

0

У моєму випадку це були не .pycстарі .moфайли бінарних перекладів після того, як я перейменував власний модуль, тому всередині цієї папки модуля мені довелося запустити

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

(будь ласка, зробіть резервну копію та спробуйте виправити .pycфайли спочатку)


0

Це також може статися, якщо у вас неправильний файл python27.dll (у випадку Windows), щоб вирішити цю проблему, просто перевстановіть (або витягніть) python з точно відповідною версією dll. У мене був подібний досвід.


0

Я щойно стикався з тією ж проблемою, що і Fedora26, коли багато інструментів, таких як dnf, були зламані через неправильне магічне число для шести. З невідомої причини у мене є файл /usr/bin/six.pyc, з несподіваним магічним номером. Видалення цього файлу усуне проблему


0

У моєму випадку у мене git cloneє гурт, у якого був перекладач

#!/usr/bin/env python

Хоча pythonце призводило до Python2.7того, що мій основний код працює з python3.6 ... він все ще створив *.pycфайл для2.7 версії ...

Я можу сказати, що ця помилка, ймовірно, є результатом поєднання 2,7 та 3+ версій, тому очищення (будь-яким чином ви можете подумати про те, що ви використовуєте) - допоможе тут ...

  • не забудьте відрегулювати ці Python2x-код -> python 3 ...

-1

Не видаляйте їх !!! Поки ..........

Знайдіть версію своєї папки git, svn або копіюйте, яка працює.

Видаліть їх, а потім відновіть усі .pyc.

Це для мене робота.


ой, чому я маю -1? це справді працює для мене, і я опинився в дуже поганій ситуації
lauralacarra

2
повернення до попередньої версії не є глобальним рішенням
ZiTAL

4
Чому б ти коли-небудь робив свої *.pycфайли?
Манос Кунелакіс

Це звичайна помилка. Якщо ви не налаштуєте файл git ігнорування правильно. Тому я даю рішення, і тоді ви повинні замовити свій git.
lauralacarra

-1

Вам потрібно буде запустити цю команду в кожному шляху, який є у вашому оточенні.

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

Потім запустіть команду в кожному каталозі тут

find /usr/lib/python3.6/ -name "*.pyc" -delete
find /usr/local/lib/python3.6/dist-packages -name "*.pyc" -delete
# etc...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.