Как узнать магическое число для заголовка.pyc в Python 3
Файлы байт-кода Python (.pyc) имеют заголовок, который начинается с магического числа, которое изменяется между версиями Python. Как я могу (программно) узнать это число для текущей версии Python, чтобы сгенерировать действительный заголовок? В настоящее время я жестко программирую код для Python 3.7.1, но это означает, что теперь я зависел от конкретной версии Python.
Этот ответ делает именно то, что я хочу, используя py_compile.MAGIC
, но этого, похоже, больше не существует в Python 3. Как я могу сделать эквивалент в Python 3?
Вот пример того, что я пытаюсь сделать:
import dis
import marshal
PYC_HEADER = b'\x42\x0d\x0d\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
def f():
print('Hello World')
with open('test.pyc', 'wb') as pyc:
pyc.write(PYC_HEADER)
marshal.dump(dis.Bytecode(f).codeobj, pyc)
Это должно создать файл test.pyc
, который затем можно запустить, используя тот же интерпретатор Python, что и скрипт, и вывести "Hello World!". И это так, но только при использовании Python 3.7. Я ищу способ, который генерирует заголовок для любой версии Python 3, используемой для запуска сценария, а не для жесткого кодирования 3.7.
Для контекста:
Я собираю простой язык программирования для различных форматов байт-кода (LLVM, байт-код Java, веб-сборка и теперь байт-код Python) как часть запланированной серии руководств по построению компилятора.
Я могу сгенерировать байт-код Python, используя библиотеку byteasm, которая в результате дает мне функцию. Но для того, чтобы записать содержимое в .pyc
файл, мне нужен правильный заголовок. При жестком кодировании заголовка код будет работать только в том случае, если люди, следующие руководству, используют ту же версию Python 3, что и я (3.7), или им придется вручную узнать магическое число для своей версии.
2 ответа
Начиная с Python 3.4 есть importlib.util.MAGIC_NUMBER
в модулеimportlib
:
>>> import importlib
>>> importlib.util.MAGIC_NUMBER.hex()
'420d0d0a'
Другое решение для Python < 3.4 или Python2 - это get_magic
методimp
модуль.
>>> import imp
>>> imp.get_magic().hex()
'420d0d0a'
Обратите внимание, что хотя это все еще работает в Python 3.7, оно устарело с Python 3.4
Это переехало! 1
>>> import importlib.util
>>> importlib.util.MAGIC_NUMBER
b'3\r\r\n'
Вероятно, проще всего обернуть это в попытке / за исключением отступления к py_compile
,