将行号传递给嵌入式Python解释器

时间:2014-07-18 14:19:11

标签: python c python-3.x python-c-api cpython

所以我有一个C程序,它使用嵌入式CPython解释器来执行Python代码。问题是如果Python代码有错误,解释器提供的行号信息就没用了,因为每次调用PyEval_EvalCodeEx都会开始计算1行。所以,我想给出每当我执行代码时,Python解释器就行号而言是一个上下文。

有办法做到这一点吗?查看PyEval_EvalCodeEx的定义,它最终是Python C-API公开的代码执行的最低级函数,我没有看到任何传递行号信息的机会。

文档只是阅读:

  
PyObject* PyEval_EvalCodeEx(PyObject *co, PyObject *globals, PyObject
*locals, PyObject **args, int argcount, PyObject **kws, int kwcount, PyObject **defs, int defcount, PyObject *closure)
     
    

在给定特定环境的情况下,评估预编译的代码对象     评价。这个环境包括全球和世界的词典     局部变量,参数数组,关键字和默认值,以及a     关闭细胞元组。

  

这是不可能做到的?

1 个答案:

答案 0 :(得分:1)

如果你看一下PyEval_EvalCodeEx()的实现,你可能会看到第一个参数被转换为PyCodeObject *,就在函数体的开头:

/* File: ceval.c */

PyObject *
PyEval_EvalCodeEx(PyObject *_co, ...)
{
    PyCodeObject* co = (PyCodeObject*)_co;
    ...
}

如果您查看PyCodeObject,就会有一个名为co_firstlineno的成员:

/* File: code.h */

typedef struct {
    PyObject_HEAD
    ...
    PyObject *co_filename;  /* unicode (where it was loaded from) */
    PyObject *co_name;      /* unicode (name, for reference) */
    int co_firstlineno;     /* first source line number */
    PyObject *co_lnotab;    /* string (encoding addr<->lineno mapping) See
                               Objects/lnotab_notes.txt for details. */
    ...
} PyCodeObject;

所以我想在调用co_firstfileno函数之前修改PyEval_EvalCodeEx()字段可能就足够了,如下所示:

((PyCodeObject *)co)->co_firstlineno = 42;
PyEval_EvalCodeEx(co, ...);

这应该足够了,据我所知,你甚至不需要修改co_lnotab,因为它包含来自co_firstlineno的偏移,而不是绝对位置。