美文网首页大数据 爬虫Python AI SqlPython小哥哥
扩展和嵌入Python之获取程序出错信息 !

扩展和嵌入Python之获取程序出错信息 !

作者: 14e61d025165 | 来源:发表于2019-03-30 14:44 被阅读0次

    接着我们上次的内容继续。简单回顾下,上次的这种嵌入方式在Python中称为纯嵌入,我们可以定义自己的模块,在模块中定义自己的函数,通过C API可以让Python解释器识别我们的自定义模块。

    在程序调试的过程中,难免会有错误产生,谁也不希望程序出错后一点提示信息也没有,然后就挂了。就像程序员最不喜欢写文档,然后也很痛恨接手的项目没有文档一样~~~如何获取嵌入Python的报错信息,就是本次的主要内容。

    回想当时在网上找了好久,终于完成了上一次的程序,还兴奋了好一会儿~~但接下来的问题就是如何获取程序的出错信息。在基于上一次的程序基础上,得出的最终结果是不行!惊不惊喜?刺不刺激?翻阅了网上大部分文章,得出一个非常一致的结论,要用下面的代码片段:PyObject *ptype = NULL, *pvalue = NULL, *ptraceback = NULL;

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

    PyErr_NormalizeException(&ptype,&pvalue,&ptraceback);(可有可无)

    if(pvalue)

    {

    ......

    }

    但是,并没有说在哪添加......试了N多次无果。最终读了N次stackoverflow(英语还是很重要),从前辈们的只言片语中发现了秘密...帖子的时间好像是2013年吧...

    OK,老规矩,直接“上马”。Python学习群:683380553,有大牛答疑,有资源共享!是一个非常不错的交流基地!欢迎喜欢Python的小伙伴!

    void Widget::on_pbn_runPython_clicked()

    {

    qDebug() << "enter python !";
    
    PyImport_AppendInittab("dahe", &PyInit_math);
    
    Py_Initialize();
    
    if (!Py_IsInitialized())
    
    {
    
        qDebug() << "inital faild!";
    
    }
    
    PyRun_SimpleString("import dahe");
    
    QFile f("/root/Python/Article/compilePython/dhTest.py");
    
    if(!f.open(QFile::ReadOnly | QFile::Text))
    
    {
    
        qDebug() << "read file faild:" << qPrintable(f.errorString());
    
    }
    
    QTextStream stream(&f);
    
    QString test = stream.readAll();
    
    QByteArray ba = test.toLatin1();
    
    const char * script_source = ba.data();
    
    PyObject* main = PyModule_GetDict(PyImport_AddModule("__main__"));
    
    PyObject *res = PyRun_String(script_source,Py_file_input,main,main);
    
    if(res == NULL)
    
    {
    
        PyObject *ptype = NULL, *pvalue = NULL, *ptraceback = NULL;
    
        PyErr_Fetch(&ptype,&pvalue,&ptraceback);
    
        PyErr_NormalizeException(&ptype,&pvalue,&ptraceback);
    
        if(pvalue)
    
        {
    
            PyObject *pstr = PyObject_Str(pvalue);
    
            if(pstr) {
    
                const char* err_msg = PyUnicode_AsUTF8(pstr);
    
                if(pstr)
    
                {
    
                    printf("%s----\n",err_msg);
    
                }
    
            }
    
        }
    
        char *msg, *file, *text;
    
        int line, offset;
    
        int res = PyArg_ParseTuple(pvalue,"s(siis)",&msg,&file,&line,&offset,&text);
    
        Q_UNUSED(res);
    
        PyObject* line_no = PyObject_GetAttrString(pvalue,"lineno");
    
        PyObject* line_no_str = PyObject_Str(line_no);
    
        PyObject* line_no_unicode = PyUnicode_AsEncodedString(line_no_str,"utf-8", "Error");
    
        char *actual_line_no = PyBytes_AsString(line_no_unicode);
    
        printf("actual_line_no --%s\n",actual_line_no);
    
    }
    
    Py_Finalize();
    

    }

    上述代码是前一次内容的修改,重复部分不再赘述。

    使用QFile读取存储文件的内容,该部分简单略过。

    在这里看到了PyErr_Fetch(&ptype,&pvalue,&ptraceback)该函数是如何使用的,需要先“编译”python文件,在编译过程中出错才可以调用该函数捕获出错信息。PyObject *res = PyRun_String(script_source,Py_file_input,main,main)注意后面的两个main,如果传为NULL,有时测试出错会报出PyEval_EvalCodeEx: NULL globals这个出错信息,注意下。

    PyErr_NormalizeException(&ptype,&pvalue,&ptraceback)该函数用于将异常信息格式化输出,根据需要来使用。不使用的话会捕获到更原始的信息。

    PyObject pstr = PyObject_Str(pvalue) 、const char err_msg = PyUnicode_AsUTF8(pstr),python C API中的类型大多是PyObject ,这里提供了一种转为c中char的方法。

    Q_UNUSED(res),Qt中提供的一种消除无用参数警告的方式,该宏的函数原型是(void)()。

    程序的最后部分是获取出错信息的位置,也就是行号。Pvalue捕获的是出错的内容,有时也会有行号。

    至此,程序简单说明结束。下面给出脚本内容以及捕获的具体出错内容。

    <tt-image data-tteditor-tag="tteditorTag" contenteditable="false" class="syl1553928146897 ql-align-center" data-render-status="finished" data-syl-blot="image" style="box-sizing: border-box; cursor: text; text-align: left; color: rgb(34, 34, 34); font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial; display: block;"> image <input class="pgc-img-caption-ipt" placeholder="图片描述(最多50字)" value="" style="box-sizing: border-box; outline: 0px; color: rgb(102, 102, 102); position: absolute; left: 187.5px; transform: translateX(-50%); padding: 6px 7px; max-width: 100%; width: 375px; text-align: center; cursor: text; font-size: 12px; line-height: 1.5; background-color: rgb(255, 255, 255); background-image: none; border: 0px solid rgb(217, 217, 217); border-radius: 4px; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);"></tt-image> <tt-image data-tteditor-tag="tteditorTag" contenteditable="false" class="syl1553928146903 ql-align-center" data-render-status="finished" data-syl-blot="image" style="box-sizing: border-box; cursor: text; text-align: left; color: rgb(34, 34, 34); font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", "Helvetica Neue", Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial; display: block;"> image

    <input class="pgc-img-caption-ipt" placeholder="图片描述(最多50字)" value="" style="box-sizing: border-box; outline: 0px; color: rgb(102, 102, 102); position: absolute; left: 187.5px; transform: translateX(-50%); padding: 6px 7px; max-width: 100%; width: 375px; text-align: center; cursor: text; font-size: 12px; line-height: 1.5; background-color: rgb(255, 255, 255); background-image: none; border: 0px solid rgb(217, 217, 217); border-radius: 4px; transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);"></tt-image>

    相关文章

      网友评论

        本文标题:扩展和嵌入Python之获取程序出错信息 !

        本文链接:https://www.haomeiwen.com/subject/xiojbqtx.html