我正在编写一段代码,它从C / C ++应用程序运行Python函数。为了做到这一点,我设置了PYTHONPATH并按如下方式运行初始化:
Py_SetPythonHome("../Python27");
Py_InitializeEx(0);
然后我导入我的模块并运行我的功能。它很棒。
我现在正在尝试为同事构建一个安装程序来运行我的代码。我想最大限度地减少我需要在此安装程序中包含的文件数量,原因很明显。
在网上搜索主题告诉我,我应该能够包含文件" Python27.lib"和" Python27.dll",然后压缩" DLLs"和#34; Lib"文件夹并包含它们。但是,当我尝试这个时,Py_Initialize失败了。
快速检查导致此失败的原因显示Py_Initialize似乎依赖于Lib文件夹中的许多.pyc文件,包括(但不限于 warnings.pyc , _abcoll .pyc , _future_.pyc 以及"编码"文件夹的内容。
我无法理解为什么会这样。有什么建议吗?
答案 0 :(得分:2)
一开始,我想说 Py_InitializeEx 不需要模块(至少没有 non-builtin ),所以唯一的要求是 python27.dll (btw: python27.lib 不是必需的,除非你的同事想要链接某些东西 - 但这不是很容易/ o Python 的包括 dir)。我有这个代码( BTW :我正在使用 Python 2.7.10 ,我使用 VStudio 10 (< EM> 2010 )):
#include <stdio.h>
#include <conio.h>
#include <Python.h>
int main() {
int i = 0;
char *pyCode =
"s = \"abc\"\n"
"print s, 1234";
Py_InitializeEx(0);
i = PyRun_SimpleString(pyCode);
Py_Finalize();
printf("PyRun_SimpleString returned: %d\nPress a key to exit...\n", i);
_getch();
return 0;
}
它构建正常,从 VStudio 和命令行(在其文件夹中复制 .dll 之后)运行正常。但后来我将 .exe 和 .dll 复制到另一台计算机上,在运行时, bang !!!
ImportError: No module named site
考虑到:
我不知道为什么它的行为不一样(我没有检查的一件事是机器上可能有一些注册表项有用吗?)。
注意:网站是位于%PYTHON_INSTALL_DIR%\ Lib .py(c))模块>
然后,我浏览了 Python 的源代码,我遇到了这个(文件: pythonrun.c ,行: 269 ,函数 Py_InitializeEx 或 pythonrun.c:269:Py_InitializeEx - 这就是我要在源代码中引用一个点的方式):
if (!Py_NoSiteFlag)
initsite(); /* Module site */
在 pythonrun.c:727:initsite :
m = PyImport_ImportModule("site");
非常明显( Py_NoSiteFlag 为0)。
然后我注意到 Py_NoSiteFlag 被声明为extern __declspec(dllexport)
([MS.Docs]: Using extern to Specify Linkage,[MS.Docs]: dllexport, dllimport),所以我将我的代码修改为:
#include <stdio.h>
#include <conio.h>
#include <Python.h>
extern __declspec(dllimport) int Py_NoSiteFlag;
int main() {
int i = 0;
char *pyCode =
"s = \"abc\"\n"
"print s, 1234";
Py_NoSiteFlag = 1;
Py_InitializeEx(0);
i = PyRun_SimpleString(pyCode);
Py_Finalize();
printf("PyRun_SimpleString returned: %d\nPress a key to exit...\n", i);
_getch();
return 0;
}
它有效!耶!
因此,此时只需运行 .dll 即可运行一段代码。但我认为你的代码“比它更复杂”(它有 import s([Python 2.Docs]: The import statement)。解决导入问题问题,你可以使用这个漂亮的模块:[Python 2.Docs]: modulefinder - Find modules used by a script( Python 2.7 的标准模块的一部分)。使用它:
以下是我的代码示例(我的 C 程序中的 pyCode 内容,保存在文件中)。
code.py :
s = "abc"
print s, 1234
运行:
%PYTHON_INSTALL_DIR%\python -m modulefinder code.py
的产率:
Name File ---- ---- m __main__ code.py
但是,如果我在文件中添加import os
(这是一个非常常见的模块)语句,上面的命令会产生:
Name File ---- ---- m StringIO %PYTHON_INSTALL_DIR%\lib\StringIO.py m UserDict %PYTHON_INSTALL_DIR%\lib\UserDict.py m __builtin__ m __future__ %PYTHON_INSTALL_DIR%\lib\__future__.py m __main__ a.py m _abcoll %PYTHON_INSTALL_DIR%\lib\_abcoll.py m _codecs m _collections m _functools m _hashlib %PYTHON_INSTALL_DIR%\DLLs\_hashlib.pyd m _heapq m _io m _locale m _random m _sre m _struct m _subprocess m _threading_local %PYTHON_INSTALL_DIR%\lib\_threading_local.py m _warnings m _weakref m _weakrefset %PYTHON_INSTALL_DIR%\lib\_weakrefset.py m abc %PYTHON_INSTALL_DIR%\lib\abc.py m array m atexit %PYTHON_INSTALL_DIR%\lib\atexit.py m bdb %PYTHON_INSTALL_DIR%\lib\bdb.py m binascii m cPickle m cStringIO m cmd %PYTHON_INSTALL_DIR%\lib\cmd.py m codecs %PYTHON_INSTALL_DIR%\lib\codecs.py m collections %PYTHON_INSTALL_DIR%\lib\collections.py m copy %PYTHON_INSTALL_DIR%\lib\copy.py m copy_reg %PYTHON_INSTALL_DIR%\lib\copy_reg.py m difflib %PYTHON_INSTALL_DIR%\lib\difflib.py m dis %PYTHON_INSTALL_DIR%\lib\dis.py m doctest %PYTHON_INSTALL_DIR%\lib\doctest.py m dummy_thread %PYTHON_INSTALL_DIR%\lib\dummy_thread.py P encodings %PYTHON_INSTALL_DIR%\lib\encodings\__init__.py m encodings.aliases %PYTHON_INSTALL_DIR%\lib\encodings\aliases.py m errno m exceptions m fnmatch %PYTHON_INSTALL_DIR%\lib\fnmatch.py m functools %PYTHON_INSTALL_DIR%\lib\functools.py m gc m genericpath %PYTHON_INSTALL_DIR%\lib\genericpath.py m getopt %PYTHON_INSTALL_DIR%\lib\getopt.py m gettext %PYTHON_INSTALL_DIR%\lib\gettext.py m hashlib %PYTHON_INSTALL_DIR%\lib\hashlib.py m heapq %PYTHON_INSTALL_DIR%\lib\heapq.py m imp m inspect %PYTHON_INSTALL_DIR%\lib\inspect.py m io %PYTHON_INSTALL_DIR%\lib\io.py m itertools m keyword %PYTHON_INSTALL_DIR%\lib\keyword.py m linecache %PYTHON_INSTALL_DIR%\lib\linecache.py m locale %PYTHON_INSTALL_DIR%\lib\locale.py P logging %PYTHON_INSTALL_DIR%\lib\logging\__init__.py m marshal m math m msvcrt m nt m ntpath %PYTHON_INSTALL_DIR%\lib\ntpath.py m opcode %PYTHON_INSTALL_DIR%\lib\opcode.py m operator m optparse %PYTHON_INSTALL_DIR%\lib\optparse.py m os %PYTHON_INSTALL_DIR%\lib\os.py m os2emxpath %PYTHON_INSTALL_DIR%\lib\os2emxpath.py m pdb %PYTHON_INSTALL_DIR%\lib\pdb.py m pickle %PYTHON_INSTALL_DIR%\lib\pickle.py m posixpath %PYTHON_INSTALL_DIR%\lib\posixpath.py m pprint %PYTHON_INSTALL_DIR%\lib\pprint.py m random %PYTHON_INSTALL_DIR%\lib\random.py m re %PYTHON_INSTALL_DIR%\lib\re.py m repr %PYTHON_INSTALL_DIR%\lib\repr.py m select %PYTHON_INSTALL_DIR%\DLLs\select.pyd m shlex %PYTHON_INSTALL_DIR%\lib\shlex.py m signal m sre_compile %PYTHON_INSTALL_DIR%\lib\sre_compile.py m sre_constants %PYTHON_INSTALL_DIR%\lib\sre_constants.py m sre_parse %PYTHON_INSTALL_DIR%\lib\sre_parse.py m stat %PYTHON_INSTALL_DIR%\lib\stat.py m string %PYTHON_INSTALL_DIR%\lib\string.py m strop m struct %PYTHON_INSTALL_DIR%\lib\struct.py m subprocess %PYTHON_INSTALL_DIR%\lib\subprocess.py m sys m tempfile %PYTHON_INSTALL_DIR%\lib\tempfile.py m textwrap %PYTHON_INSTALL_DIR%\lib\textwrap.py m thread m threading %PYTHON_INSTALL_DIR%\lib\threading.py m time m token %PYTHON_INSTALL_DIR%\lib\token.py m tokenize %PYTHON_INSTALL_DIR%\lib\tokenize.py m traceback %PYTHON_INSTALL_DIR%\lib\traceback.py m types %PYTHON_INSTALL_DIR%\lib\types.py P unittest %PYTHON_INSTALL_DIR%\lib\unittest\__init__.py m unittest.case %PYTHON_INSTALL_DIR%\lib\unittest\case.py m unittest.loader %PYTHON_INSTALL_DIR%\lib\unittest\loader.py m unittest.main %PYTHON_INSTALL_DIR%\lib\unittest\main.py m unittest.result %PYTHON_INSTALL_DIR%\lib\unittest\result.py m unittest.runner %PYTHON_INSTALL_DIR%\lib\unittest\runner.py m unittest.signals %PYTHON_INSTALL_DIR%\lib\unittest\signals.py m unittest.suite %PYTHON_INSTALL_DIR%\lib\unittest\suite.py m unittest.util %PYTHON_INSTALL_DIR%\lib\unittest\util.py m warnings %PYTHON_INSTALL_DIR%\lib\warnings.py m weakref %PYTHON_INSTALL_DIR%\lib\weakref.py Missing modules: ? _emx_link imported from os ? ce imported from os ? fcntl imported from subprocess, tempfile ? org.python.core imported from copy, pickle ? os.path imported from os, shlex ? os2 imported from os ? posix imported from os ? pwd imported from posixpath ? readline imported from cmd, pdb ? riscos imported from os ? riscosenviron imported from os ? riscospath imported from os
正如您所看到的,有很多模块(我稍微修改了输出,而不是我放置%PYTHON_INSTALL_DIR% env var的实际路径)。为了使 Python 代码能够工作,您必须在安装程序中包含所有这些模块/包。
注意关于 modulefinder 的输出(我在玩它时注意到了):
因此,查看 os 所需的模块,我不确定从 C 中取出 site 导入很大的不同。
重要提示:要确保 .exe 可在任何计算机上运行,您可以考虑包含 VStudio C运行时库或 VCRTLib ( msvcr ##(#)。dll :[MS.Docs]: Run-Time Library Reference)(其中#是数字的占位符 - 在安装程序中代表 VStudio 版本。