C 中的嵌入式 python:有没有办法从压缩的 python 存档中正确导入 numpy?

Posted

技术标签:

【中文标题】C 中的嵌入式 python:有没有办法从压缩的 python 存档中正确导入 numpy?【英文标题】:Embedded python in C : Is there a way to import numpy properly from zipped python archive? 【发布时间】:2017-10-05 17:43:01 【问题描述】:

当使用包含所有 python 文件和二进制文件的本地 .zip python 文件而不是标准 python 安装时,似乎我无法从嵌入 python 的 C 应用程序中正确导入 numpy。这是我得到的错误:

zipimport:zlib 可用 python27.zip\Lib\site-packages\numpy_globals.pyc 的 mtime 错误 zipimport:zlib 可用 import numpy._globals # 从 Zip 加载 python27.zip\Lib\site-packages\numpy_globals.py zipimport:zlib 可用 python27.zip\Lib\site-packages\numpy__config__.pyc 的 mtime 错误 zipimport:zlib 可用 import numpy.config # 从 Zip 加载 python27.zip\Lib\site-packages\numpy__config__.py zipimport:zlib 可用 python27.zip\Lib\site-packages\numpy\version.pyc 的 mtime 错误 zipimport:zlib 可用 import numpy.version # 从 Zip 加载 python27.zip\Lib\site-packages\numpy\version.py zipimport:zlib 可用 python27.zip\Lib\site-packages\numpy_import_tools.pyc 的 mtime 错误 zipimport:zlib 可用 import numpy._import_tools # 从 Zip 加载 python27.zip\Lib\site-packages\numpy_import_tools.py zipimport:zlib 可用 python27.zip\Lib\site-packages\numpy\add_newdocs.pyc 的 mtime 错误 zipimport:zlib 可用 zipimport:zlib 可用 导入数学#内置 zipimport:zlib 可用 import numpy.lib.info # 从 Zip 加载 python27.zip\Lib\site-packages\numpy\lib\info.pyc zipimport:zlib 可用 zipimport:zlib 可用 zipimport:zlib 可用 python27.zip\Lib\site-packages\numpy\core\info.pyc 的 mtime 错误 zipimport:zlib 可用 import numpy.core.info # 从 Zip 加载 python27.zip\Lib\site-packages\numpy\core\info.py import numpy.core # 从 Zip 加载 python27.zip\Lib\site-packages\numpy\core__init__.pyc import numpy.lib.type_check # 从 Zip 加载 python27.zip\Lib\site-packages\numpy\lib\type_check.pyc import numpy.lib # 从 Zip 加载 python27.zip\Lib\site-packages\numpy\lib__init__.pyc import numpy.add_newdocs # 从 Zip 加载 python27.zip\Lib\site-packages\numpy\add_newdocs.py import numpy # 从 Zip 加载 python27.zip\Lib\site-packages\numpy__init__.py无法导入名称多数组

但是当我提取上述 .zip 文件并运行 python.exe 解释器并导入 numpy 时,一切正常。

我已经从源代码 x86 Release 构建了 python 2.7.13。之后从here 安装 numpy-1.11.3+mkl-cp27-cp27m-win32.whl 文件,然后制作一个 python .zip 存档,其中包含所有必需文件,遵循通用文件夹结构。

这就是我的 C 代码的样子:

int main(int argc, char **argv)

    Py_VerboseFlag++;
    Py_NoSiteFlag++;

    Py_SetProgramName(argv[0]);
    Py_SetPythonHome(".");

    Py_Initialize();

    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path = ['.','python27.zip','python27.zip/DLLs','python27.zip/Lib', 'python27.zip/Lib/site-packages']");;
    PyRun_SimpleString("print sys.path");

    printf("\n");

    char filename[_MAX_PATH];
    _fullpath(filename, "mod1.py", _MAX_PATH);

    PyObject* main_module = PyImport_AddModule("__main__");
    PyObject* main_dict = PyModule_GetDict(main_module);
    PyObject *pyFileObj = PyFile_FromString(filename, "r");

    if (pyFileObj == NULL) 
        return -1;
    

    FILE *pFile = PyFile_AsFile(pyFileObj);

    if (pFile == NULL)
        return -1;

    PyObject *result = PyRun_File(pFile, filename, Py_file_input, main_dict, main_dict);

    if (!result)
        print_error();

    printf("\n\n");


    Py_Finalize();
    getchar();

    return 0;

模块 mod1.py,我正在执行包含这个:

import time
import json
import numpy

if __name__ == "__main__":
    print 'Success'

我知道该错误来自 python 无法加载共享库 multiarray.pyd 的事实。在导入时我需要单独处理这种情况吗? 是否可以从 C 应用程序的压缩、非标准 python 安装中正确导入 numpy?

编辑:忘记提及以下内容: - 我的操作系统是 Windows 10 x64 版本 1511(操作系统内部版本 10586.545) - 当我在我的 C 应用程序二进制文件所在的 Release 文件夹中提取 .zip 存档时,一切正常,numpy 使用以下 sys.path

正确加载
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path = ['.', 'DLLs', 'Lib', 'Lib\\site-packages', 'Sources']");
PyRun_SimpleString("print sys.path");

EDIT 2:另外,考虑检查 python27.dll 链接到的 multiarray.pyd 的确切版本(根据其他帖子关于类似的问题),结果发现它与我的不同 - 它是 2.7.8。没问题,从 .msi 包中提取特定的 python27.dll v2.7.8 二进制文件并替换我的 2.7.13,但仍然没有运气。这绝对是关于 zipimport 模块的东西。

【问题讨论】:

您无法从 zip 文件加载共享库。这是操作系统的限制,适用于 Windows、Linux 和 Mac OS。这不是 Python 或其 zip 文件导入器的问题。由于 Numpy 包含 C 扩展,因此您不能将其捆绑在 zip 可执行文件中。 感谢您的回答,我已经学会了这个艰难的方法。但是,我想我是通过利用 Joachim Bauch 编写的 MemoryModule lib 将存档解压缩到内存中并加载来实现的(在 Win 上)来自那里的东西。示例代码在这里:github.com/Civa/continuum/blob/master/src/continuum/runtime/…(警告:由于我还在学习 C,所以代码写得很糟糕,代码很乱) 有趣的是,我最终为 Linux 做了类似的事情;从概念上讲,它是一个包装器,将二进制文件复制到 /tmp 中的文件夹中,将文件夹添加到 sys.path 并评估 from mymodule import * 以加载扩展。我不知道这个加载器。 对不起@JasonArg123,我已经从 github 迁移了所有东西,并且可能在此过程中删除了过时的存储库。找到源码后我会上传到gitlab @JasonArg123 here 是我找到的旧仓库。如果你想了解 loader 的工作原理,只需搜索loader.c。请注意,此代码非常混乱。因为这是为 Windows 编写的,所以我很久以前就切换到 LInux,所以我帮不上什么忙,抱歉。请随意对代码做任何你想做的事情,因为没有附加许可证。希望你会发现它很有用。干杯,西瓦 【参考方案1】:

最好的方法可能是现在解压缩它。 zipimport 模块是 Python 用来从 zip 文件中加载模块的模块,不幸的是它不允许导入动态编译代码(可能是出于安全考虑,与 PEP 273 一致):

zip 存档中可能存在任何文件,但只有文件 *.py 和 .py[co] 可用于导入。 动态模块(.pyd、*.so)的压缩导入是不允许的。

由于提供的***将是平台***,因此您还需要从 Cython 添加的 .so 文件名中删除平台扩展名,以遵守PEP 3149。即,foo.cpython-XYm.so 需要重命名为 foo.so。 (由于您的问题是关于 Python 2,这并不适用,但它确实适用于 Python 3)

最后,解压后的文件夹必须是added to the PYTHONPATH,如果它们还没有的话。

【讨论】:

感谢您的回复,但我早就放弃了那个项目。 没问题,在 Spark 集群上遇到过这个问题,所以我做了深入调查,希望其他人不必这样做

以上是关于C 中的嵌入式 python:有没有办法从压缩的 python 存档中正确导入 numpy?的主要内容,如果未能解决你的问题,请参考以下文章

python中有没有办法解压缩类似于javascript中的传播运算符的列表? [复制]

go路由httprouter中的压缩字典树算法图解及c++实现

没有pip的嵌入式Python手动安装包

在python中读取csv压缩文件

如何使用 Python 将文件压缩为受密码保护的存档

有没有办法从嵌入式 ViewController 更改 Tabbar 图像和操作?