带有 Python 嵌入的 C++:如果未安装 Python,则会崩溃

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1387906/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 22:06:57  来源:igfitidea点击:

C++ with Python embedding: crash if Python not installed

pythonc++dllembed

提问by apostrophest

I'm developing on Windows, and I've searched everywhere without finding anyone talking about this kind of thing.

我在 Windows 上开发,我到处搜索,但没有找到任何人谈论这种事情。

I made a C++ app on my desktop that embedded Python 3.1 using MSVC. I linked python31.lib and included python31.dll in the app's run folder alongside the executable. It works great. My extension and embedding code definitely works and there are no crashes.

我在我的桌面上制作了一个 C++ 应用程序,它使用 MSVC 嵌入了 Python 3.1。我链接了 python31.lib 并在应用程序的运行文件夹中包含了 python31.dll 和可执行文件。它工作得很好。我的扩展和嵌入代码绝对有效并且没有崩溃。

I sent the run folder to my friend who doesn't have Python installed, and the app crashes for him during the scripting setup phase.

我将运行文件夹发送给我没有安装 Python 的朋友,在脚本设置阶段应用程序崩溃了。

A few hours ago, I tried the app on my laptop that has Python 2.6installed. I got the same crash behavior as my friend, and through debugging found that it was the Py_Initialize() call that fails.

几个小时前,我在安装了Python 2.6 的笔记本电脑上试用了该应用程序。我遇到了和我朋友一样的崩溃行为,通过调试发现是 Py_Initialize() 调用失败了。

I installed Python 3.1 on my laptop without changing the app code. I ran it and it runs perfectly. I uninstalled Python 3.1 and the app crashes again. I put in code in my app to dynamically link from the local python31.dll, to ensure that it was using it, but I still get the crash.

我在我的笔记本电脑上安装了 Python 3.1,而没有更改应用程序代码。我运行它,它运行完美。我卸载了 Python 3.1,应用程序再次崩溃。我在我的应用程序中放入代码以从本地 python31.dll 动态链接,以确保它正在使用它,但我仍然遇到崩溃。

I don't know if the interpreter needs more than the DLL to start up or what. I haven't been able to find any resources on this. The Python documentation and other guides do not seem to ever address how to distribute your C/C++ applications that use Python embedding without having the users install Python locally. I know it's more of an issue on Windows than on Unix, but I've seen a number of Windows C/C++ applications that embed Python locally and I'm not sure how they do it.

我不知道解释器是否需要比 DLL 更多的启动或什么。我一直无法找到有关此的任何资源。Python 文档和其他指南似乎从未解决如何在不让用户在本地安装 Python 的情况下分发使用 Python 嵌入的 C/C++ 应用程序。我知道这在 Windows 上比在 Unix 上更像是一个问题,但我已经看到许多在本地嵌入 Python 的 Windows C/C++ 应用程序,我不确定它们是如何做到的。

What else do I need other than the DLL? Why does it work when I install Python and then stop working when I uninstall it? It sounds like it should be so trivial; maybe that's why nobody really talks about it. Nevertheless, I can't really explain how to deal with this crash issue.

除了 DLL 之外,我还需要什么?为什么当我安装 Python 时它可以工作,然后在我卸载它时停止工作?听起来它应该如此微不足道;也许这就是为什么没有人真正谈论它。尽管如此,我无法真正解释如何处理这个崩溃问题。

Thank you very much in advance.

非常感谢您提前。

回答by Martin v. L?wis

In addition to pythonxy.dll, you also need the entire Python library, i.e. the contents of the lib folder, plus the extension modules, i.e. the contents of the DLLs folder. Without the standard library, Python won't even start, since it tries to find os.py (in 3.x; string.py in 2.x). On startup, it imports a number of modules, in particular site.py.

除了pythonxy.dll,你还需要整个Python库,即lib文件夹的内容,加上扩展模块,即DLLs文件夹的内容。如果没有标准库,Python 甚至无法启动,因为它会尝试查找 os.py(在 3.x 中;在 2.x 中为 string.py)。在启动时,它会导入许多模块,特别是 site.py。

There are various locations where it searches for the standard library; in your cases, it eventually finds it in the registry. Before, uses the executable name (as set through Py_SetProgramName) trying to find the landmark; it also checks for a file python31.zip which should be a zipped copy of the standard library. It also checks for a environment variable PYTHONHOME.

它搜索标准库的位置有很多;在您的情况下,它最终会在注册表中找到它。之前,使用可执行名称(通过 Py_SetProgramName 设置)试图找到地标;它还检查文件 python31.zip,它应该是标准库的压缩副本。它还检查环境变量 PYTHONHOME。

You are free to strip the library from stuff that you don't need; there are various tools that compute dependencies statically (modulefinder in particular).

您可以自由地从不需要的东西中剥离库;有各种工具可以静态计算依赖项(特别是 modulefinder)。

If you want to minimize the number of files, you can

如果你想尽量减少文件的数量,你可以

  1. link all extension modules statically into your pythonxy.dll, or even link pythonxy.dll statically into your application
  2. use the freeze tool; this will allow linking the byte code of the standard library into your pythonxy.dll.
  3. (alternatively to 2.) use pythonxy.zip for the standard library.
  1. 将所有扩展模块静态链接到您的 pythonxy.dll,甚至将 pythonxy.dll 静态链接到您的应用程序
  2. 使用冻结工具;这将允许将标准库的字节码链接到您的 pythonxy.dll。
  3. (或者 2。)使用 pythonxy.zip 作为标准库。

回答by sambha

Nice. And if you do not want to zip, copy Python26\DLLs & Python26\lib to your exe directory as:

好的。如果您不想压缩,请将 Python26\DLLs & Python26\lib 复制到您的 exe 目录中,如下所示:

.\myexe.exe       
.\python26.dll
.\Python26\DLLs
.\Python26\lib

And then set PYTHONHOME with Py_SetPythonHome() API. Apparently, this API is not in the list of "allowed" calls beforePy_Initialize();

然后使用 Py_SetPythonHome() API 设置 PYTHONHOME。显然,这个 API 不在Py_Initialize()之前的“允许”调用列表中;

Below worked for me on Windows (Python not installed):

下面在 Windows 上对我来说有效(未安装Python ):

#include "stdafx.h"
#include <iostream>
#include "Python.h"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
   char pySearchPath[] = "Python26";
   Py_SetPythonHome(pySearchPath);
   Py_Initialize();
   PyRun_SimpleString("from time import time,ctime\n"
                     "print 'Today is',ctime(time())\n");
   //cerr << Py_GetPath() << endl;
   Py_Finalize();

    return 0;
}

Good that the search path is relative w.r.t the exe. Py_GetPath can show you where all it is looking for the modules.

很好,搜索路径是相对于 exe 的。Py_GetPath 可以向您显示它正在寻找模块的位置。

回答by user1185601

A zip of the Python standard library worked for me with Python27.

Python 标准库的 zip 文件适用于 Python27。

I zipped the contentsof Lib and dll, and made sure there was no additional python27-subfolder or Lib or dll subfolder. i.e. just a zip named python27.zip containing all the files.

我压缩Lib 和 dll的内容,并确保没有额外的 python27-subfolder 或 Lib 或 dll 子文件夹。即只是一个包含所有文件的名为 python27.zip 的 zip。

I copied that zip and the python27.dll alongside the executable.

我将那个 zip 和 python27.dll 与可执行文件一起复制。

回答by djangodude

I wanted to add some additional info for others who might still be having troubles with this, as I was. I was eventually able to get my application working using the method proposed by user sambha, that is:

我想为其他可能仍然遇到问题的人添加一些额外的信息,就像我一样。我最终能够使用用户 sambha 提出的方法让我的应用程序工作,即:

Program Files (x86)\
    MyApplicationFolder\
        MyApplication.exe
        python27.dll
        Python27\
            DLLs\ (contents of DLLs folder)
            Lib\ (contents of Lib folder)

...with one importantaddition: I also needed to install the MSVCR90.DLL. I'm using Python 2.7 and apparently python27.dll requires the MSVCR90.DLL (and maybe other MSVC*90.DLLs).

...还有一个重要的补充:我还需要安装 MSVCR90.DLL。我正在使用 Python 2.7,显然 python27.dll 需要 MSVCR90.DLL(可能还有其他 MSVC*90.DLL)。

I solved this by downloading, installing, and running the 'vcredist_x86.exe' package from http://www.microsoft.com/en-us/download/details.aspx?id=29. I think, though I am not certain, that you need to do it this way at least on Win7, as opposed to simply placing the MSVC*90.DLLs alongside your .exe as you may have done in the past. The Microsoft installer places the files and registers them in a special way under Win7.

我通过从http://www.microsoft.com/en-us/download/details.aspx?id=29下载、安装和运行“vcredist_x86.exe”包解决了这个问题。我认为,虽然我不确定,您至少需要在 Win7 上这样做,而不是像过去那样简单地将 MSVC*90.DLL 与 .exe 放在一起。Microsoft 安装程序在 Win7 下以特殊方式放置文件并注册它们。

I also tried the .zip file method but that did not work, even with the MSVCR90.DLL installed.

我还尝试了 .zip 文件方法,但即使安装了 MSVCR90.DLL,也没有奏效。