一开始,我想说的是在Py_InitializeEx中不需要任何模块(至少没有非内置模块), 所以唯一的要求是python27.dll (顺便说一下: python27.lib 不是必需的,除非你的同事想要链接它 - 但这并不容易,没有Python的Includedir).
我有这段代码(使用Python 2.7.10,我使用VStudio 10(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复制到另一台计算机上运行时,就出现了问题!!!
ImportError: No module named site
考虑到:
我不知道为什么它们的表现不一样(我还没有检查的一件事是可能有一些注册表键在工作的机器上?)。
注意:site 是位于 %PYTHON_INSTALL_DIR%\Lib 下的 (.py(c)) 模块。
然后,我浏览了Python的源代码,并发现[GitHub]: python/cpython - (v2.7.10) cpython/Python/pythonrun.c(函数Py_InitializeEx - 目前在第#141行)- 这是我将要引用源代码中的一个点:
if (!Py_NoSiteFlag)
initsite();
在 initsite 中:
m = PyImport_ImportModule("site");
这是非常明显的(Py_NoSiteFlag 是 0)。
然后我注意到 Py_NoSiteFlag 被声明为 extern __declspec(dllexport)
([MS.Learn]: 使用 extern 指定链接, [MS.Learn]: 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即可运行一段代码。但我想你的代码“有点”复杂(它有imports ([Python 2.Docs]:导入语句)。为了解决import问题,您可以使用这个不错的模块:[Python 2.Docs]:modulefinder-查找脚本使用的模块(是Python 2.7标准模块的一部分)。使用它:
将您从C执行的代码保存在.py文件中
运行modulefinder对其进行分析
以下是我的代码的示例(保存在文件中的C程序中的pyCode内容)。
code00.py:
s = "abc"
print(s, 1234)
运行中:
${PYTHON_INSTALL_DIR}\python.exe -m modulefinder code00.py
产生:
Name File
---- ----
m __main__ code00.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.Learn]:运行时库参考)(其中*#*是数字的占位符-代表VStudio版本)。