Py_Initialize 到 运行 需要哪些文件?
What files are required for Py_Initialize to run?
我正在编写一段简单的代码,它 运行 是来自 C/C++ 应用程序的 Python 函数。为此,我设置了 PYTHONPATH 并 运行 初始化如下:
Py_SetPythonHome("../Python27");
Py_InitializeEx(0);
然后我导入我的模块和 运行 我的函数。效果很好。
我现在正在尝试为我的同事构建一个安装程序以 运行 我的代码。出于明显的原因,我想尽量减少需要包含在此安装程序中的文件数量。
围绕该主题进行谷歌搜索告诉我应该能够包含文件 "Python27.lib" 和 "Python27.dll",然后压缩 "DLLs" 和 "Lib" 文件夹并包含它们.但是,当我尝试这样做时,Py_Initialize 失败了。
快速检查导致此失败的原因表明 Py_Initialize 似乎依赖于 Lib 文件夹中的许多 .pyc 文件,包括(但不限于 warnings.pyc、_abcoll.pyc、_future_.pyc和"encodings"文件夹的内容。
我不明白为什么会这样。有什么建议吗?
一开始我想说Py_InitializeEx[=不需要模块(至少不需要非内置一个) 153=], 所以唯一的要求是 python27.dll (BTW: python27.lib 不需要,除非你的同事想 link 反对它 - 但这不是很容易 w / o Python的Include dir)。
我有这段代码(使用 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;
}
构建良好,运行 OK 来自 VStudio,并来自命令行(复制 .dll 在其文件夹中)。但后来我将 .exe 和 .dll 复制到另一台计算机,当 运行ning 时,砰!!!
ImportError: No module named site
考虑到:
- 我在我 运行 .exe(结果不同)
- 在两台机器上,Python 安装在相同的路径上(我之前(几年前)在机器上修改过它,但它不起作用)
我不知道为什么它的行为不一样(我没有检查的一件事是机器上可能有一些可用的注册表项?)。
注意: site是一个(.py(c )) 模块位于 %PYTHON_INSTALL_DIR%\Lib.
然后,我浏览了Python的源码,来到across [GitHub]: python/cpython - (v2.7.10) cpython/Python/pythonrun.c(函数 Py_InitializeEx - 当前行 #141) - 就是这样我将引用源代码中的一点):
if (!Py_NoSiteFlag)
initsite(); /* Module site */
在 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 即可 运行 一段代码。但我想你的代码比那“有点”复杂(它有 imports ([Python 2.Docs]: The import statement). To solve the import problem, you can use this nice module: [Python 2.Docs]: modulefinder - Find modules used by a script(部分Python 2.7的标准模块。要使用它:
- 将您从 C 执行的代码保存在 .py 文件中
- 运行 modulefinder反对
这是我的代码示例(pyCode 内容在我的 C 程序中,保存在文件中)。
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 代码起作用,您必须在安装程序中包含所有 ose modules/packages。
注释 关于 modulefinder 的输出(我在玩它时注意到):
- 它递归地搜索模块,所以这是整个模块依赖树
- 它搜索位于函数中的 import 语句(因此,不仅是模块级别的语句)
- 它不搜索动态导入s(例如[Python 2.Docs]: __import__(name[, globals[, locals[, fromlist[, level]]]]))
所以,查看 os 所需的模块,我不确定取出 site 从 C 导入,差别很大。
重要说明:为确保您的 .exe 可以在任何计算机上运行,您可以考虑包括 VStudio C 运行时间库 或 VCRTLib (msvcr##(#).dll: [MS.Docs]: Run-Time Library Reference)(其中 *#*s 是数字的占位符 - 代表 VStudio 版本)在您的安装程序中。
我正在编写一段简单的代码,它 运行 是来自 C/C++ 应用程序的 Python 函数。为此,我设置了 PYTHONPATH 并 运行 初始化如下:
Py_SetPythonHome("../Python27");
Py_InitializeEx(0);
然后我导入我的模块和 运行 我的函数。效果很好。
我现在正在尝试为我的同事构建一个安装程序以 运行 我的代码。出于明显的原因,我想尽量减少需要包含在此安装程序中的文件数量。
围绕该主题进行谷歌搜索告诉我应该能够包含文件 "Python27.lib" 和 "Python27.dll",然后压缩 "DLLs" 和 "Lib" 文件夹并包含它们.但是,当我尝试这样做时,Py_Initialize 失败了。
快速检查导致此失败的原因表明 Py_Initialize 似乎依赖于 Lib 文件夹中的许多 .pyc 文件,包括(但不限于 warnings.pyc、_abcoll.pyc、_future_.pyc和"encodings"文件夹的内容。
我不明白为什么会这样。有什么建议吗?
一开始我想说Py_InitializeEx[=不需要模块(至少不需要非内置一个) 153=], 所以唯一的要求是 python27.dll (BTW: python27.lib 不需要,除非你的同事想 link 反对它 - 但这不是很容易 w / o Python的Include dir)。
我有这段代码(使用 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;
}
构建良好,运行 OK 来自 VStudio,并来自命令行(复制 .dll 在其文件夹中)。但后来我将 .exe 和 .dll 复制到另一台计算机,当 运行ning 时,砰!!!
ImportError: No module named site
考虑到:
- 我在我 运行 .exe(结果不同)
- 在两台机器上,Python 安装在相同的路径上(我之前(几年前)在机器上修改过它,但它不起作用)
我不知道为什么它的行为不一样(我没有检查的一件事是机器上可能有一些可用的注册表项?)。
注意: site是一个(.py(c )) 模块位于 %PYTHON_INSTALL_DIR%\Lib.
然后,我浏览了Python的源码,来到across [GitHub]: python/cpython - (v2.7.10) cpython/Python/pythonrun.c(函数 Py_InitializeEx - 当前行 #141) - 就是这样我将引用源代码中的一点):
if (!Py_NoSiteFlag)
initsite(); /* Module site */
在 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 即可 运行 一段代码。但我想你的代码比那“有点”复杂(它有 imports ([Python 2.Docs]: The import statement). To solve the import problem, you can use this nice module: [Python 2.Docs]: modulefinder - Find modules used by a script(部分Python 2.7的标准模块。要使用它:
- 将您从 C 执行的代码保存在 .py 文件中
- 运行 modulefinder反对
这是我的代码示例(pyCode 内容在我的 C 程序中,保存在文件中)。
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 代码起作用,您必须在安装程序中包含所有 ose modules/packages。
注释 关于 modulefinder 的输出(我在玩它时注意到):
- 它递归地搜索模块,所以这是整个模块依赖树
- 它搜索位于函数中的 import 语句(因此,不仅是模块级别的语句)
- 它不搜索动态导入s(例如[Python 2.Docs]: __import__(name[, globals[, locals[, fromlist[, level]]]]))
所以,查看 os 所需的模块,我不确定取出 site 从 C 导入,差别很大。
重要说明:为确保您的 .exe 可以在任何计算机上运行,您可以考虑包括 VStudio C 运行时间库 或 VCRTLib (msvcr##(#).dll: [MS.Docs]: Run-Time Library Reference)(其中 *#*s 是数字的占位符 - 代表 VStudio 版本)在您的安装程序中。