在实际开发中,Python作为解释型语言,在实际的代码分发过程中,有比较多的格式定义:.pyc\.pyd\.pyo\.pyz。一直想对它们理一下,东拼西凑的整理了下面的内容,主要也回答了自己的一些问题。
当您导入一个模块时,类型为.pyc的文件将由解释器自动生成,这将加速该模块未来的导入。因此,这些文件仅在由另一个.py文件或模块导入时从.py文件创建。
注意,使用.pyc文件只会加快程序的加载速度,而不会加快程序的实际执行速度。这意味着您可以通过在一个模块中编写主程序来提高启动时间,这个模块由另一个更小的模块导入。
pyc主要写入三个内容:
1. Magic num
2. Pyc创建时间
3. PyCodeObject.(python/marshal.c)
Python在不同的版本,pyc的头部长度和内容是不同的:
l PEP 3147:
.pyc文件包含两个32位大端数字,后面跟的序列化的PyCodeObject。32位数字表示一个Magic Num和Timestamp。每当Python改变字节码格式时,Magic Num会改变,例如,通过向其虚拟机添加新的字节码。这确保为以前版本的VM构建的pyc文件不会造成问题。Timestamp用于确保pyc文件与用于创建它的py文件匹配。当Magic Num或Timestamp不匹配时,将重新编译py文件并写入新的pyc文件。
l PEP 552:
pyc头文件目前由3个32位的字组成。我们将把它扩大到4个。第一个单词将继续是magic number,对字节码和pyc格式进行版本控制。第二个4byte新增加的字段,将是一个位字段(bit field),对报头其余部分的解释和pyc的失效行为取决于位字段的内容。
如果位字段(bit field)为0,则pyc是传统的基于时间戳的pyc。即第三个和第四个4字节内容分别是时间戳和文件大小,通过比较源文件的元数据和头文件中的元数据来进行无效判断。
如果位字段的最低位被设置,则pyc是基于哈希的pyc。我们将第二个最低位称为check_source标志。位字段之后是源文件的64位散列。我们将使用带有源文件内容硬编码密钥。另一个类似MD5或BLAKE2的快速散列也可以。我们选择SipHash是因为Python已经从PEP 456中获得了它的内置实现,尽管允许选择SipHash键的接口必须公开给Python。散列的安全性不是一个问题,尽管我们传递完全破碎的散列(如MD5)来简化在受控环境中对Python的审计。
对于Magic值,它的逻辑为:后2bytes为0D0A,前面的值满足: [min, max]范围,版本信息定义参考结构内容,示例分析代码如下:
```
typedef struct {
unsigned short min;
unsigned short max;
wchar_t version[MAX_VERSION_SIZE];
} PYC_MAGIC;
static PYC_MAGIC magic_values[] = {
{ 50823, 50823, L"2.0" },
{ 60202, 60202, L"2.1" },
{ 60717, 60717, L"2.2" },
{ 62011, 62021, L"2.3" },
{ 62041, 62061, L"2.4" },
{ 62071, 62131, L"2.5" },
{ 62151, 62161, L"2.6" },
{ 62171, 62211, L"2.7" },
{ 3000, 3131, L"3.0" },
{ 3141, 3151, L"3.1" },
{ 3160, 3180, L"3.2" },
{ 3190, 3230, L"3.3" },
{ 3250, 3310, L"3.4" },
{ 3320, 3351, L"3.5" },
{ 3360, 3379, L"3.6" },
{ 3390, 3399, L"3.7" },
{ 3400, 3419, L"3.8" },
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2019-12-16 11:57
被nevinhappy编辑
,原因: 上传附件。