如何找出 Python 中 .pyc header 的幻数 3

How to find out the magic number for the .pyc header in Python 3

Python 字节码 (.pyc) 文件有一个 header,它以一个在 Python 版本之间变化的幻数开头。我如何(以编程方式)找出当前 Python 版本的数字以生成有效的 header?我目前 hard-coding Python 3.7.1,但这意味着我现在依赖于特定的 Python 版本。

This answer 使用 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 用于 运行 脚本的任何版本生成 header,而不是 hard-coding 3.7.

对于上下文:

我正在将一种简单的编程语言编译成不同的字节码格式(LLVM、Java 字节码、Web Assembly 和现在的 Python 字节码),作为计划中的编译器构造教程系列的一部分。

我可以使用 the byteasm library 生成 Python 字节码,这给了我一个函数。但是为了将内容写入 .pyc 文件,我需要一个有效的 header。通过 hard-coding 和 header,只有跟随本教程的人 运行 与我 (3.7) 使用相同版本的 Python 3,或者他们' d 必须手动找出他们版本的幻数。

从 Python 3.4 开始,模块 importlib:

中有 importlib.util.MAGIC_NUMBER
>>> import importlib
>>> importlib.util.MAGIC_NUMBER.hex()
'420d0d0a'

Python < 3.4 或 Python2 的另一个解决方案是 get_magic method of the imp module.

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

New in version 3.4.

可能最简单的方法是将其包装在 try/except 中以退回到 py_compile