如何将Python模块(来自PyObject*)转换并保存为二进制数据,以便以后使用

How convert and save Python module (from PyObject*) as binary data to use it later?

本文关键字:数据 二进制 保存 转换 模块 Python 来自 PyObject      更新时间:2023-10-16

我正在用Python/C API做一些测试,以了解它是如何工作的以及如何正确使用它。我的目标是创建C++包装器,使我能够从C++代码运行Python脚本。我不能使用外部bindind库(如Boost.Python或Cython)。一切都很顺利,除了一件事:现在,我正在使用PyImport_Import()加载脚本

PyObject* py_module = PyImport_Import(py_module_name); //imports *.py file
//do something, call functions, save results
PyDecRef(py_module);

然而,在发行版中,它们必须以专有的二进制格式分发,并在启动时加载到内存中。我一直在寻找一些如何实现这一目标的提示——但没有结果。基本上,我需要做这样的事情:

File* file = fopen("scripts.bin", "rb");
char* c_buff = malloc(...);
fread(c_buff, file, ...);
PyObject* py_module = CreatePyObjectFromBinaryData(c_buff, ...);

smeone能提供可能的解决方案吗?我曾想过以这种方式使用编组功能:

FILE* file = fopen("scripts.bin", "wb");
PyMarshal_WriteObjectToFile(py_module, file, Py_MARSHAL_VERSION);

然而,这似乎并不奏效。事实上,我不确定什么对象可以用这种方式进行编组,因为文档中没有任何关于它的内容

可选问题:我的二进制文件夹中有所有*.py文件。启动时,在PyImport_Import()之后,它们被隐含地编译为/pycache中的字节码(.pyc)。我知道字节码文件(.pyc或*.pyo)可以使用compileall模块创建。是否可以使用此类文件的内容创建包含模块数据的PyObject?

只发送.pyc文件可以接受吗?试试这样的东西:

int size;
unsigned char *python_code;
PyObject *mainobj;
size = load_file("multiply.pyc", &python_code);    
Py_Initialize();
codeobj = PyMarshal_ReadObjectFromString(python_code+8, size-8);
mainobj = PyImport_ExecCodeModule("multiply", codeobj);
Py_Finalize();

查看此讨论。。。https://groups.google.com/forum/#!topic/comp.lang.python/zhIe_AA2h8 Caersten Haese在哪里说:

pyc文件包含以下内容:

1) 包含幻数的8字节标头。2) "元帅"代码对象的序列化。

因此,为了将这些内容转换为代码对象,您需要跳过8字节的报头并对其余部分进行解组。

使用包含.pyc文件的加密zip文件失败了吗?(您需要在c++代码中对pwd进行编码)。

我认为,如果你不信任客户,真正安全的东西真的很难(不可能?)。