
Magic number в Python – это специальное числовое значение, которое помещается в заголовок скомпилированного байткода (.pyc файла) и определяет совместимость с конкретной версией интерпретатора. Например, для Python 3.11 magic number равен 62161, а для Python 3.10 – 62061. Интерпретатор проверяет это число при загрузке .pyc файла, чтобы убедиться, что байткод можно выполнить.
Игнорирование magic number может привести к ошибкам загрузки модулей или неожиданному поведению программы. Например, попытка выполнить .pyc файл, скомпилированный в Python 3.10, в Python 3.11 вызовет ImportError: bad magic number. Проверка и правильная настройка magic number особенно важны при переносе проектов между различными версиями Python или при работе с кэшированными байткодами.
Для проверки magic number можно использовать модуль importlib.util и функцию MAGIC_NUMBER. Также возможно программно создавать или исправлять .pyc файлы, чтобы соответствовать текущей версии интерпретатора. Понимание этой механики помогает избегать проблем с загрузкой модулей и упрощает поддержку кэшированного байткода в больших проектах.
Определение magic number в контексте Python

Magic number позволяет интерпретатору определить, подходит ли файл байткода для текущей версии Python. Если число не совпадает, загрузка .pyc завершается с ошибкой ImportError: bad magic number. Это предотвращает выполнение несовместимого байткода и обеспечивает стабильность работы программы.
Для анализа magic number можно открыть .pyc файл в бинарном режиме и прочитать первые 4 байта. Для создания новых .pyc файлов важно использовать актуальное значение magic number, иначе интерпретатор откажется их загружать. Рекомендовано автоматически пересобирать байткод при обновлении версии Python, чтобы соответствие magic number оставалось корректным.
Как Python использует magic number для определения версии байткода

Каждая версия Python имеет уникальный magic number. Ниже приведены примеры соответствий:
| Версия Python | Magic number |
|---|---|
| 3.9 | 62061 |
| 3.10 | 62061 |
| 3.11 | 62161 |
| 3.12 | 62211 |
При разработке проектов важно учитывать, что перенос .pyc файлов между версиями Python без пересборки приведет к ошибкам. Рекомендуется пересобирать байткод с помощью compileall или автоматического импорта, чтобы magic number соответствовал текущей версии интерпретатора.
Проверка magic number в существующих.pyc файлах

Для проверки magic number в .pyc файле можно открыть его в бинарном режиме и считать первые 4 байта. В Python это делается с помощью стандартного модуля builtins и функции open в режиме ‘rb’. Считанное значение следует сравнить с текущей константой importlib.util.MAGIC_NUMBER.
Пример проверки в коде:
with open(‘example.pyc’, ‘rb’) as f:
magic = f.read(4)
print(magic)
Для массовой проверки рекомендуется использовать модуль importlib.util совместно с функцией compileall. Это позволяет одновременно идентифицировать устаревшие байткоды и пересобрать их, чтобы они соответствовали текущей версии Python.
Создание собственных файлов с корректным magic number

Для создания .pyc файлов с правильным magic number важно учитывать версию Python и структуру байткода. Интерпретатор автоматически вставляет актуальное значение MAGIC_NUMBER при компиляции, но при ручном создании нужно следовать определённым шагам.
Рекомендации по созданию корректных .pyc файлов:
- Использовать модуль compileall для пакетной компиляции исходных .py файлов.
- Для одиночной компиляции применять py_compile.compile() с указанием пути к выходному .pyc файлу.
- При ручной записи байткода вставлять первые 4 байта с актуальным importlib.util.MAGIC_NUMBER.
- Следить за порядком байтов: Python использует little-endian для MAGIC_NUMBER.
- Обновлять байткод при изменении версии интерпретатора, чтобы исключить bad magic number.
Пример создания .pyc файла через py_compile:
import py_compile
py_compile.compile(‘example.py’, cfile=’example.pyc’)
Такой подход гарантирует, что созданный файл будет загружаться без ошибок и полностью совместим с текущей версией Python.
Обновление magic number при изменении версии Python
Каждая версия Python использует уникальный magic number для идентификации байткода. При переходе на новую версию интерпретатора старые .pyc файлы становятся несовместимыми. Попытка их загрузки приведёт к ошибке ImportError: bad magic number.
Для корректного обновления magic number рекомендуется:
- Удалять старые .pyc файлы из каталогов __pycache__ перед запуском новой версии Python.
- Использовать compileall.compile_dir() для пересборки всех исходных файлов и автоматической установки актуального magic number.
- При ручной компиляции применять py_compile.compile(), чтобы сгенерированные .pyc файлы содержали правильное значение MAGIC_NUMBER.
- Проверять соответствие magic number с помощью importlib.util.MAGIC_NUMBER перед распространением байткода между машинами.
Соблюдение этих правил позволяет избежать ошибок загрузки модулей и гарантирует совместимость байткода с новой версией интерпретатора.
Использование модуля importlib для работы с magic number
Модуль importlib предоставляет инструменты для работы с байткодом и проверки magic number без прямого открытия .pyc файлов. Константа importlib.util.MAGIC_NUMBER содержит актуальное значение magic number для текущей версии Python.
Примеры практического использования:
- Проверка соответствия существующих .pyc файлов текущей версии интерпретатора:
import importlib.util
with open(‘example.pyc’, ‘rb’) as f:
magic = f.read(4)
if magic != importlib.util.MAGIC_NUMBER:
print(«Несовпадающий magic number»)
- Использование importlib для загрузки модулей с пересборкой байткода, если magic number устарел.
- Автоматизация пересборки .pyc файлов с помощью importlib.util.cache_from_source() для генерации пути к актуальному файлу байткода.
Применение importlib позволяет программно управлять совместимостью байткода, предотвращать ошибки загрузки и упрощает поддержку проектов при обновлении версии Python.
Практические примеры ошибок из-за неправильного magic number
- Попытка выполнить .pyc файл, скомпилированный в Python 3.9, на Python 3.11.
- Копирование .pyc файлов между проектами с разными версиями интерпретатора без пересборки.
- Использование устаревшего кэша __pycache__, когда интерпретатор обновлён, но старые файлы не удалены.
Примеры исправления ошибок:
- Удаление всех файлов .pyc и каталогов __pycache__ перед запуском проекта на новой версии Python.
- Пересборка байткода с помощью py_compile.compile() для отдельных файлов или compileall.compile_dir() для целых каталогов.
- Проверка magic number с помощью importlib.util.MAGIC_NUMBER и автоматическая идентификация устаревших .pyc файлов.
Соблюдение этих шагов предотвращает ошибки загрузки модулей и гарантирует совместимость байткода с используемой версией Python.
Вопрос-ответ:
Что такое magic number в Python и зачем оно используется?
Magic number — это числовое значение в первых 4 байтах .pyc файла, которое определяет версию байткода. Python проверяет его при загрузке, чтобы убедиться, что байткод совместим с текущей версией интерпретатора. Если значение не совпадает, возникает ошибка ImportError: bad magic number. Это помогает избежать выполнения модулей, которые могут быть несовместимы с интерпретатором.
Как проверить magic number в существующих .pyc файлах?
Для проверки нужно открыть .pyc файл в бинарном режиме и считать первые 4 байта. Например, в Python можно использовать код: with open(‘example.pyc’, ‘rb’) as f: magic = f.read(4). Полученное значение сравнивается с importlib.util.MAGIC_NUMBER. Если значения не совпадают, это значит, что файл был скомпилирован для другой версии Python и его нужно пересобрать.
Можно ли вручную создавать .pyc файлы с правильным magic number?
Да, но это требует точного соблюдения структуры файла и корректного значения magic number. Проще использовать модуль py_compile или compileall. При ручной записи нужно вставить первые 4 байта с актуальным importlib.util.MAGIC_NUMBER и следить за порядком байтов (little-endian). Ручное создание оправдано только при специфических сценариях автоматизации или тестирования байткода.
Что произойдет, если обновить Python, но не пересобрать .pyc файлы?
При попытке загрузки старых .pyc файлов с несовпадающим magic number интерпретатор выдаст ImportError: bad magic number. Это происходит, потому что байткод был скомпилирован для предыдущей версии Python. Решение — удалить устаревшие .pyc файлы или пересобрать их с помощью compileall, чтобы обновленный байткод соответствовал текущей версии.
Как модуль importlib помогает работать с magic number?
Модуль importlib позволяет получить актуальное значение magic number через importlib.util.MAGIC_NUMBER и автоматически формировать пути к файлам байткода с помощью importlib.util.cache_from_source(). Это облегчает проверку совместимости .pyc файлов и упрощает пересборку байткода при обновлении версии Python, предотвращая ошибки загрузки модулей.
