c++ Py_Initialize运行需要哪些文件?

6psbrbz9  于 2023-05-08  发布在  其他
关注(0)|答案(1)|浏览(104)

我正在编写一段简单的代码,它从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.pycfuture.pyc 和“encodings”文件夹的内容。
我不明白为什么会这样。有什么建议吗

zf9nrax1

zf9nrax11#

一开始,我想说 Py_InitializeEx 不需要模块(至少没有 * 非内置 * 一个),所以唯一的要求是 python27.dllBTW:*python27.lib不是必需的,除非你的同事想链接一些东西来反对它-但这并不容易 w / o**PythonInclude**dir)。
我有这样的代码(使用 Python 2.7.10,我使用 VStudio102010)构建):

#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 之后)运行 OK。但是后来我把 .exe.dll 复制到另一台计算机上,当运行时,砰!!!

ImportError: No module named site

考虑到:

  • 我在运行 .exe 的2台计算机上的两个控制台中都没有设置 PYTHON**env vars*(结果不同)
  • 在这两台机器上,Python 安装在相同的路径上(我以前(几年前)在不工作的机器上修改了它)

我不知道为什么它的行为不一样(有一件事,我还没有检查是,可能有一些注册表键的机器上的工作?).

注意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(); /* Module site */

while in***initsite***:

m = PyImport_ImportModule("site");

这是非常明显的(Py_NoSiteFlag 是***0***)。
然后我注意到 Py_NoSiteFlag 被声明为extern __declspec(dllexport)[MS.Learn]: Using extern to Specify Linkage[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 是必需的,以运行一段代码。但是我想你的代码比这“稍微”复杂一点(它有***import***s([Python 2.Docs]: The import statement))。要解决 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 的输出注意事项(我在玩它的时候注意到的):

  • 它递归地搜索模块,所以这里是整个模块依赖关系树
  • 它搜索位于函数中的 import 语句(因此,不仅仅是模块级别的语句)
  • 搜索动态 * 导入 *s(例如【Python 2.Docs】:import(name[,globals[,locals [,fromlist[,level]]]))

所以,看看 os 所需的模块,我不确定从 C 中取出 site 导入会有多大不同。

重要提示:要确保您的 .exe 在任何计算机上都能运行,您可以考虑包括 *VStudio C运行时库 * 或 VCRTLibmsvcr##(#).dll[MS.Learn]: Run-Time Library Reference)(其中 *#*s是数字的占位符-代表 VStudio 版本)。

相关问题