有没有方法知道.pyc文件是由哪个Python版本编译的?
有没有办法知道一个 .pyc
文件是用哪个版本的 Python 编译的呢?
6 个回答
17
或者,如果你使用的是GNU/Linux系统,可以在终端里输入“file”这个命令:
$ file code.pyc
> code.pyc: python 3.5.2 byte-compiled
61
.pyc
文件的前两个字节是一个魔法数字,用来表示字节码的版本。这个数字是以小端格式存储的,已知的值如下:
Python 版本 | 十进制 | 十六进制 | 备注 |
---|---|---|---|
Python 1.5 | 20121 | 0x994e | |
Python 1.5.1 | 20121 | 0x994e | |
Python 1.5.2 | 20121 | 0x994e | |
Python 1.6 | 50428 | 0x4cc4 | |
Python 2.0 | 50823 | 0x87c6 | |
Python 2.0.1 | 50823 | 0x87c6 | |
Python 2.1 | 60202 | 0x2aeb | |
Python 2.1.1 | 60202 | 0x2aeb | |
Python 2.1.2 | 60202 | 0x2aeb | |
Python 2.2 | 60717 | 0x2ded | |
Python 2.3a0 | 62011 | 0x3bf2 | |
Python 2.3a0 | 62021 | 0x45f2 | |
Python 2.3a0 | 62011 | 0x3bf2 | ! |
Python 2.4a0 | 62041 | 0x59f2 | |
Python 2.4a3 | 62051 | 0x63f2 | |
Python 2.4b1 | 62061 | 0x6df2 | |
Python 2.5a0 | 62071 | 0x77f2 | |
Python 2.5a0 | 62081 | 0x81f2 | ast-branch |
Python 2.5a0 | 62091 | 0x8bf2 | with |
Python 2.5a0 | 62092 | 0x8cf2 | 更改了 WITH_CLEANUP 操作码 |
Python 2.5b3 | 62101 | 0x95f2 | 修复错误代码: for x, in ... |
Python 2.5b3 | 62111 | 0x9ff2 | 修复错误代码: x += yield |
Python 2.5c1 | 62121 | 0xa9f2 | 修复错误的 lnotab,涉及 for 循环和应该被移除的常量存储 |
Python 2.5c2 | 62131 | 0xb3f2 | 修复错误代码: for x, in ... 在列表推导/生成表达式中 |
Python 2.6a0 | 62151 | 0xc7f2 | 进行 peephole 优化和 STORE_MAP 操作码 |
Python 2.6a1 | 62161 | 0xd1f2 | WITH_CLEANUP 优化 |
Python 2.7a0 | 62171 | 0xdbf2 | 优化列表推导/更改 LIST_APPEND |
Python 2.7a0 | 62181 | 0xe5f2 | 优化条件分支: 引入 POP_JUMP_IF_FALSE 和 POP_JUMP_IF_TRUE |
Python 2.7a0 | 62191 | 0xeff2 | 引入 SETUP_WITH |
Python 2.7a0 | 62201 | 0xf9f2 | 引入 BUILD_SET |
Python 2.7a0 | 62211 | 0x03f3 | 引入 MAP_ADD 和 SET_ADD |
Python 3000 | 3000 | 0xb80b | |
3010 | 0xc20b | 移除 UNARY_CONVERT |
|
3020 | 0xcc0b | 添加 BUILD_SET |
|
3030 | 0xd60b | 添加仅关键字参数 | |
3040 | 0xe00b | 添加签名注解 | |
3050 | 0xea0b | print 变成了一个函数 |
|
3060 | 0xf40b | PEP 3115 元类语法 | |
3061 | 0xf50b | 字符串字面量变成了 Unicode | |
3071 | 0xff0b | PEP 3109 抛出变化 | |
3081 | 0x090c | PEP 3137 使 __file__ 和 __name__ 成为 Unicode |
|
3091 | 0x130c | 移除 str8 共享 | |
3101 | 0x1d0c | 从 2.6a0 合并,见 62151 | |
3103 | 0x1f0c | __file__ 指向源文件 |
|
Python 3.0a4 | 3111 | 0x270c | WITH_CLEANUP 优化 |
Python 3.0a5 | 3131 | 0x3b0c | 词法异常堆栈,包括 POP_EXCEPT |
Python 3.1a0 | 3141 | 0x450c | 优化列表、集合和字典推导: 更改 LIST_APPEND 和 SET_ADD ,添加 MAP_ADD |
Python 3.1a0 | 3151 | 0x4f0c | 优化条件分支: 引入 POP_JUMP_IF_FALSE 和 POP_JUMP_IF_TRUE |
Python 3.2a0 | 3160 | 0x580c | 添加 SETUP_WITH ,标签: cpython-32 |
Python 3.2a1 | 3170 | 0x620c | 添加 DUP_TOP_TWO ,移除 DUP_TOPX 和 ROT_FOUR ,标签: cpython-32 |
Python 3.2a2 | 3180 | 0x6c0c | 添加 DELETE_DEREF |
来源:
- Python/import.c - 由 aix 从 Python 2.7.2 和 Python 3.2.2 合并
- Igor Popov 方法的前两个字节的小端十六进制值由 jimbob 添加以供比较
58
你可以通过下面的方法找到你使用的Python的魔法数字:
$ python -V
Python 2.6.2
# python
>>> import imp
>>> imp.get_magic().encode('hex')
'd1f20d0a'
如果你想获取一个pyc文件的魔法数字,可以这样做:
>>> f = open('test25.pyc')
>>> magic = f.read(4)
>>> magic.encode('hex')
'b3f20d0a'
>>> f = open('test26.pyc')
>>> magic = f.read(4)
>>> magic.encode('hex')
'd1f20d0a'
通过比较这些魔法数字,你就能知道是哪个版本的Python生成了这个pyc文件。