gpt4 book ai didi

python - 嵌入式Python(C API): How to run . py文件重复而不重新初始化

转载 作者:太空宇宙 更新时间:2023-11-03 18:51:02 25 4
gpt4 key购买 nike

我在嵌入式 python 方面遇到了很大的困难。

我正在运行一个 DLL,每次调用某个函数时我都想运行一个 Python 脚本。我想避免在函数末尾调用 Py_Finalize(),因为 Initialize/Finalize 调用大约需要 75 毫秒的时间,而我负担不起。

问题是,我似乎无法多次运行同一个 .py 文件而不会出现错误。

...
runResult = PyRun_SimpleFile(pyfileptr, pyfilename);
if (runResult)
{
if (!PyErr_Occurred())
return -4;
PyErr_Print();
return -3;
}
...

第二次我总是返回-4。我什至不知道这是怎么可能的,因为文档说如果有异常,PyRun_SimpleFile 返回 -1,否则返回 0,但 PyErr_Occurred() 在没有异常的情况下返回 NULL。

即使我正在运行的 Python 文件很简单

print("hi")

我最终得到了相同的结果,这当然让我相信这不是脚本本身生成的异常。

更新:它看起来越来越像是一个与 DLL 相关的问题,因为在独立应用程序中运行相同的代码不会显示问题。不过还是很困惑。

最佳答案

在这里。我基本上提出了两个问题,但现在我的答案有些糟糕:

如何在不重新初始化的情况下运行 python 文件?只是在第二次调用 PyRun_SimpleFile() 或 boost::python::exec_file() 之前不要调用 Finalize。

为什么 PyRun_SimpleFile() 返回非零后 PyErr_Occurred() 返回 0?简短的回答是我仍然不知道,但我最好的猜测是它与 DLL 实现和一些挂起或丢失的引用有关。

我根据 kichik 的建议使用了 boost::python,虽然我不会说它比基本 C API 更容易使用,但它更容易阅读。它也没有表现出丢失错误的问题,所以最终它解决了我的问题。即使在 DLL 中,我也能够连续执行两次 exec_file() 调用,没有出现任何问题。

因为我在寻找以我需要的方式使用 boost::python 的示例时遇到了一些困难,所以我将我的代码放在这里,稍微修剪一下空间。当然,其中一些是特定于我的项目的,但作为一般示例,它仍然可能有值(value)。

extern "C" LTPYTHON_API int ltPythonAnalyzeLog(char * analyzerfile, char * logfile, double timeWindow, int * results)
{

std::vector<int> countsVector;
Py_Initialize();
object main_module = import("__main__");
object main_namespace = main_module.attr("__dict__");
// Example of adding a variable to the global namespace
main_namespace["scriptIsRunningThroughDll"] = boost::python::long_(1);

// Load arguments for the analyzer call
{
int argc = 3;
wchar_t * argv[3];

//*... assemble wchar arguments for py script ... *

PySys_SetArgv(argc, argv);
}

int startClock = clock();
try
{
exec_file(analyzerfile, main_namespace);
}
catch(error_already_set const &)
{
//*... some error handling ...*

PyObject *ptype, *pvalue, *ptraceback;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);

handle<> hType(ptype);
object extype(hType);
handle<> hTraceback(ptraceback);
object traceback(hTraceback);

//Extract error message
std::string strErrorMessage = extract<std::string>(pvalue);
long lineno = extract<long> (traceback.attr("tb_lineno"));

FILE * outfile = fopen("ltpython-error.txt", "a");
fprintf(outfile, "%d: %s\n", lineno, strErrorMessage);
fflush(outfile);
fclose(outfile);

return -1;
}

//*... grabbing a matrix of results that were created in the script ...*
object counts = main_namespace["sortedIndicationCounts"];
list countsList = extract<list>(counts);
int totalCount = 0;
for (int i = 0; i < len(countsList); i++)
{
list singleCount = extract<list>(countsList[i]);
countsVector.push_back(extract<int>(singleCount[1]));
totalCount += countsVector[i];
}

//*... returning the number of milliseconds that elapsed ...*
return clock() - startClock;
}

错误处理基于this answer .

关于python - 嵌入式Python(C API): How to run . py文件重复而不重新初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18365907/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com