gpt4 book ai didi

python - 从 C API 访问 Python 回溯

转载 作者:IT老高 更新时间:2023-10-28 22:21:45 24 4
gpt4 key购买 nike

我在找出使用 C API 进行 Python 回溯的正确方法时遇到了一些麻烦。我正在编写一个嵌入 Python 解释器的应用程序。我希望能够执行任意 Python 代码,如果它引发异常,则将其转换为我自己的特定于应用程序的 C++ 异常。现在,只提取引发 Python 异常的文件名和行号就足够了。这是我目前所拥有的:

PyObject* pyresult = PyObject_CallObject(someCallablePythonObject, someArgs);
if (!pyresult)
{
PyObject* excType, *excValue, *excTraceback;
PyErr_Fetch(&excType, &excValue, &excTraceback);
PyErr_NormalizeException(&excType, &excValue, &excTraceback);

PyTracebackObject* traceback = (PyTracebackObject*)traceback;
// Advance to the last frame (python puts the most-recent call at the end)
while (traceback->tb_next != NULL)
traceback = traceback->tb_next;

// At this point I have access to the line number via traceback->tb_lineno,
// but where do I get the file name from?

// ...
}

在 Python 源代码中四处挖掘,我看到他们通过 _frame 结构访问当前帧的文件名和模块名,看起来它是一个私有(private)定义的结构。我的下一个想法是以编程方式加载 Python 'traceback' 模块并使用 C API 调用它的函数。这是理智的吗?有没有更好的方法从 C 访问 Python 回溯?

最佳答案

这是一个老问题,但为了将来引用,您可以从线程状态对象中获取当前堆栈帧,然后将帧向后移动。除非您想为将来保留状态,否则不需要回溯对象。

例如:

PyThreadState *tstate = PyThreadState_GET();
if (NULL != tstate && NULL != tstate->frame) {
PyFrameObject *frame = tstate->frame;

printf("Python stack trace:\n");
while (NULL != frame) {
// int line = frame->f_lineno;
/*
frame->f_lineno will not always return the correct line number
you need to call PyCode_Addr2Line().
*/
int line = PyCode_Addr2Line(frame->f_code, frame->f_lasti);
const char *filename = PyString_AsString(frame->f_code->co_filename);
const char *funcname = PyString_AsString(frame->f_code->co_name);
printf(" %s(%d): %s\n", filename, line, funcname);
frame = frame->f_back;
}
}

关于python - 从 C API 访问 Python 回溯,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1796510/

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