我正在编写一段简单的代码,它从C/C++应用程序运行Python函数。为此,我设置PYTHONPATH并运行initialize,如下所示:
Py_SetPythonHome("../Python27");
Py_InitializeEx(0);
然后导入模块并运行函数。效果很好。
我现在正试图为我的同事构建一个安装程序来运行我的代码。出于显而易见的原因,我想最大限度地减少需要包含在此安装程序中的文件数量。
在Google上搜索这个主题告诉我,我应该能够包含文件“Python27.lib”和“Python27.dll”,然后压缩“DLL”和“Lib”文件夹并包含它们。但是,当我尝试这样做时,Py_Initialize失败。
快速检查导致此故障的原因,可以发现Py_Initialize似乎依赖于Lib文件夹中的许多.pyc文件,包括(但不限于)warnings.pyc、_abcoll.pyc、future.pyc 和“encodings”文件夹的内容。
我不明白为什么会这样。有什么建议吗
1条答案
按热度按时间zf9nrax11#
一开始,我想说 Py_InitializeEx 不需要模块(至少没有 * 非内置 * 一个),所以唯一的要求是 python27.dll(BTW:*python27.lib不是必需的,除非你的同事想链接一些东西来反对它-但这并不容易 w / o**Python 的 Include**dir)。
我有这样的代码(使用 Python 2.7.10,我使用 VStudio10(2010)构建):
它构建得很好,它从 VStudio 和命令行(在复制其文件夹中的 .dll 之后)运行 OK。但是后来我把 .exe 和 .dll 复制到另一台计算机上,当运行时,砰!!!
考虑到:
我不知道为什么它的行为不一样(有一件事,我还没有检查是,可能有一些注册表键的机器上的工作?).
注意site是%PYTHON_INSTALL_DIR%\Lib**下的(.py(c)*)模块。
然后,我浏览了 Python 的源代码,我遇到了[GitHub]: python/cpython - (v2.7.10) cpython/Python/pythonrun.c(函数***Py_InitializeEx***-当前行***#141***)-这是我将如何引用源代码中的一个点):
while in***initsite***:
这是非常明显的(Py_NoSiteFlag 是***0***)。
然后我注意到 Py_NoSiteFlag 被声明为
extern __declspec(dllexport)
([MS.Learn]: Using extern to Specify Linkage,[MS.Learn]: dllexport, dllimport),所以我修改了代码:而且很有效!耶
因此,在这一点上,只有 .dll 是必需的,以运行一段代码。但是我想你的代码比这“稍微”复杂一点(它有***import***s([Python 2.Docs]: The import statement))。要解决 import 问题,您可以使用这个不错的模块:【Python 2.Docs】:modulefinder -查找脚本使用的模块(Python 2.7 标准模块的一部分)。要使用它:
下面是我的代码示例(我的 C 程序中的 pyCode 内容,保存在文件中)。
运行:
产量:
但是,如果我在文件中添加一个
import os
(这是一个很常见的模块)语句,上面的命令会产生:如您所见,有非常多的模块(我稍微修改了输出,而不是我放置 *${PYTHON_INSTALL_DIR}*env var 占位符的实际路径)。为了让 Python 代码工作,你必须在安装程序中包含所有这些模块/包。
关于 modulefinder 的输出注意事项(我在玩它的时候注意到的):
所以,看看 os 所需的模块,我不确定从 C 中取出 site 导入会有多大不同。
重要提示:要确保您的 .exe 在任何计算机上都能运行,您可以考虑包括 *VStudio C运行时库 * 或 VCRTLib(msvcr##(#).dll:[MS.Learn]: Run-Time Library Reference)(其中 *#*s是数字的占位符-代表 VStudio 版本)。