C++中嵌入的Python不能两次导入Pandas

2024-09-28 21:05:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我在C++代码中嵌入Python 3.82.(使用VisualStudio 2019)。Python安装了pandasn(通过pip)

我设法从C++程序中导入熊猫,但是,当我尝试再次导入它时,它崩溃了。p>

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

int main( int argc, char* argv[] )
{
    {
        Py_SetPythonHome( L"C:\\Python38" );

        // Initialize the Python Interpreter
        Py_Initialize();

        std::cout << "Importing pandas..." << std::endl;
        if ( PyRun_SimpleString( "import pandas" ) == 0 )
            std::cout << "SUCCESS" << std::endl;
        else
            std::cout << "FAIL" << std::endl;

        Py_Finalize();
    }

    {
        Py_SetPythonHome( L"C:\\Python38" );

        // Initialize the Python Interpreter
        Py_Initialize();

        std::cout << "Importing pandas..." << std::endl;
        if ( PyRun_SimpleString( "import pandas" ) == 0 )
            std::cout << "SUCCESS" << std::endl;
        else
            std::cout << "FAIL" << std::endl;

        Py_Finalize();
    }

    return 0;
}

这会导致一个例外:

_multiarray_umath.cp38-win_amd64.pyd!00007ffbd5b8ca69() Inconnu
_multiarray_umath.cp38-win_amd64.pyd!00007ffbd5b8ffd6() Inconnu
_multiarray_umath.cp38-win_amd64.pyd!00007ffbd5b9d34d() Inconnu
python38.dll!00007ffbd22f6131() Inconnu
python38.dll!00007ffbd22f6092() Inconnu

输出为:

Importing pandas...
SUCCESS
Importing pandas...
Traceback (most recent call last):
  File "<string>", line 1, in <module>

是否有任何初始化/取消初始化步骤我错过了,可能会使这个失败,而它可以工作

注意,我不能作为pandascannot be loaded in Debug build进行调试


Tags: pypandaswinamd64pydsuccessstdcout
1条回答
网友
1楼 · 发布于 2024-09-28 21:05:43

根据OP的要求,我制作了一个小演示,介绍如何在应用程序中包装用户Python脚本,以防止用户脚本的全局变量意外持久化:

#include <iostream>
#include <string>
#include <Python.h>

const char *PyScript = R"(try:
  print(a)
except:
  print("a not (yet) defined")
a = 123
print(a)
)";

std::string wrapPyScript(const char* script)
{
  std::string source = std::string("def __mainPythonFunction():\n") + script;
  { const char *const indent = "\n  ";
    for (size_t i = source.size(); i ;) {
      size_t n = 1;
      switch (source[i]) {
        case '\n': if (i && source[i - 1] == '\r') n = 2,  i;
        case '\r': source.replace(i, n, indent); break;
      }
    }
  }
  source += "\n"
    "pass\n"
    "\n"
    "try:\n"
    "  __mainPythonFunction()\n"
    "except:\n"
    "  rf.form.appContext.notifyAbort()\n"
    "  raise\n";
  return source;
}
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__ 

int main()
{
  DEBUG(Py_Initialize());
  std::cout << "\nWithout wrapper:\n\n";
  DEBUG(for (int i = 0; i < 2; ++i) {
    DEBUG(PyRun_SimpleString(PyScript));
  });
  std::cout << "\nWith wrapper:\n\n";
  DEBUG(for (int i = 0; i < 2; ++i) {
    DEBUG(PyRun_SimpleString(wrapPyScript(PyScript).c_str()));
  });
  std::cout << '\n';
  DEBUG(Py_Finalize());
}

输出:

Py_Initialize();

Without wrapper:

for (int i = 0; i < 2; ++i) { DEBUG(PyRun_SimpleString(PyScript)); };
PyRun_SimpleString(PyScript);
a not (yet) defined
123
PyRun_SimpleString(PyScript);
123
123

With wrapper:

for (int i = 0; i < 2; ++i) { DEBUG(PyRun_SimpleString(wrapPyScript(PyScript).c_str())); };
PyRun_SimpleString(wrapPyScript(PyScript).c_str());
a not (yet) defined
123
PyRun_SimpleString(wrapPyScript(PyScript).c_str());
a not (yet) defined
123

Py_Finalize();

但是,我不确定这是否足以解决导入的Pandas库的OPs问题

在我们的应用程序中(我们使用了上述技巧),我们在Py_Initialize()之后导入选定的库一次。 (我大致记得,这是我们最后一次不顾一切地解决类似问题,如OP观察到的问题。)

相关问题 更多 >