将python代码编译为PyCodeObject并编组为pyc文件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将python代码编译为PyCodeObject并编组为pyc文件相关的知识,希望对你有一定的参考价值。

我尝试将python代码编译为PyCodeObject并编组为pyc文件。但是当我导入我的pyc文件时,它失败并且回溯是“ValueError:错误的编组数据(未知类型代码)”这是我的代码

import struct
import marshal
import time
import imp 
import sys 

def dump(co, filename):
    magic = imp.get_magic()
    time_string = struct.pack('L', int(time.time()))
    f = open("merge.pyc", "wb")
    f.write(magic)
    f.write(time_string)
    marshal.dump(dco, f)
    f.close()

demo = open("demo.py").read()
dco = compile(demo, "demo.py", "exec")
dump(dco, "dco.pyc")
答案

我想ValueError引发的是因为时间戳的类型不匹配。您应该确保fmt中的L参数(struct.pack使用,标准大小为4个字节)与python可执行文件具有相同的长度。

由于时间戳的值不会影响最终结果,因此在这里使类型合适就足够了。如果您使用64位版本的CPython,请尝试使用Q而不是L来确保8个字节。

===更新开始===

对不起,我在前面的描述中犯了一个严重的错误。

没有任何前缀的L意味着native,并且大小和字节顺序与机器的本机格式和字节顺序相同(在64位CPython中,它将是8个字节)。但是,写入pyc文件的时间戳在Python 2和3中始终为4个字节(小端)。

如果使用的是Python2,我们应该使用<L而不是L,它具有标准大小,4个字节。

如果使用的是Python3,除了timestamp之外,我们应该添加另外4个字节的字段source size,如下面的代码所示(importlib / _bootstrap_external.py,Python3.6.4)

def _code_to_bytecode(code, mtime=0, source_size=0):
    """Compile a code object into bytecode for writing out to a byte-compiled
    file."""
    data = bytearray(MAGIC_NUMBER)
    data.extend(_w_long(mtime))
    data.extend(_w_long(source_size))
    data.extend(marshal.dumps(code))
    return data

最后,您可以参考pkgutil.read_code(),这是编写代码的相反顺序。

===更新结束===

顺便说一下,你的代码中有一些缺陷:没有在co函数中使用filenamedump参数

以上是关于将python代码编译为PyCodeObject并编组为pyc文件的主要内容,如果未能解决你的问题,请参考以下文章

如何将 c、c++ 和 python 代码编译为“Released/Final”版本? [关闭]

如何将python脚本编译为二进制可执行文件

将 Swift 编译为 WebAssembly

如何将 Python 包编译为 dll

如何为 Autodesk Maya OSX 将 py 文件编译为 .so

Python 文件编译为字节码的方法