⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pythoncexceptiontraceback.txt

📁 PythonC嵌入编程中的异常处理。介绍了如果通过PythonC提供的API函数进行异常跟踪。
💻 TXT
字号:
C代码中如何得到python脚本异常时的traceback信息
 
 
 
在软件项目的开发过程中,我们总是试图让程序能够适应更多的应用环境以及业务流程,不管你对于需求的了解如何准确,也不管你做了有多么充分的估计,但有很多情况仍然让你无法应付,比如:需求是会变化的;维护项目的人不一定都能用C/C++写出没有内存问题的代码等等。

让软件系统能够适应更多变化的方法有很多种,高度的抽象、动态链接技术等等都是一直以来被大家采用较广的方法,那么今天我们要讨论的是脚本引擎的嵌入问题。通常我更喜欢c代码加上python脚本引擎的结构,python的好处就不多说了。不过在C中嵌入python脚本引擎调用之后也有一些非常麻烦的地方,比如不便于调试,因为我们的宿主应用程序必然会为python脚本wrap一些module、class、function等等,因此这带来了调试的难度,有时候仅仅依赖print是一件非常低效的事,那么我们如何得到python脚本在异常时的traceback情况呢?比如代码出现异常到底是在哪个脚本文件中,到底是哪行代码出了问题?错误又是什么呢?我们先来看看下面的函数:


#include <Python.h>#include <compile.h>#include <frameobject.h>#include <traceback.h>voidprocess_python_exception(void){  char buf[512], *buf_p = buf;  PyObject *type_obj, *value_obj, *traceback_obj;  PyErr_Fetch(&type_obj, &value_obj, &traceback_obj);  if (value_obj == NULL)    return;  if (!PyString_Check(value_obj))    return;  char *value = PyString_AsString(value_obj);  size_t szbuf = sizeof(buf);  int l;  PyCodeObject *codeobj;  l = snprintf(buf_p, szbuf, _("Error Message:\n%s"), value);  buf_p += l;  szbuf -= l;  if (traceback_obj != NULL) {    l = snprintf(buf_p, szbuf, _("\n\nTraceback:\n"));    buf_p += l;    szbuf -= l;    PyTracebackObject *traceback = (PyTracebackObject *)traceback_obj;    for (;traceback && szbuf > 0; traceback = traceback->tb_next) {      codeobj = traceback->tb_frame->f_code;      l = snprintf(buf_p, szbuf, "%s: %s(# %d)\n",                   PyString_AsString(codeobj->co_name),                   PyString_AsString(codeobj->co_filename),                   traceback->tb_lineno);      buf_p += l;      szbuf -= l;    }  }  message_error_dialog_show(buf);  Py_XDECREF(type_obj);  Py_XDECREF(value_obj);  Py_XDECREF(traceback_obj);}

PyErr_Fetch 用来获取异常对象,并且同时可以得到traceback对象,traceback其实是一个PyTracebackObject结构体,可以在 python的头文件traceback.h中找到,PyTracebackObject其实也是一个单向链表,可以通过其tb_next成员来枚举,其 tb_frame则是一个_frame结构体,在frameobject.h头文件中可以看到,其中f_code就是我们需要的PyCodeObject 结构体,PyCodeObject中就可以得到co_name和co_filename这两个关键的描述,一个是错误信息另一个是文件名称, PyTracebackObject的tb_lineno就是出错的行号,有了这些数据我们调试还有困难吗?  
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -