【问题标题】:Passing line number to embedded Python interpreter将行号传递给嵌入式 Python 解释器
【发布时间】:2014-07-18 14:19:11
【问题描述】:

所以我有一个 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)

在给定特定环境的情况下评估预编译的代码对象 评估。该环境由全球字典和 局部变量、参数数组、关键字和默认值,以及 单元格的闭包元组。

那么这根本不可能吗?

【问题讨论】:

  • 你能不能反过来做——将行号信息存储在你的 C 程序中,捕获嵌入式解释器给你的输出,并在显示给用户之前替换正确的行数?
  • 当然可以,但是我必须解析 Python 错误消息,这似乎不太可靠。

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


【解决方案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;

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

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

这应该足够了,据我记得,您甚至不需要修改co_lnotab,因为它包含与co_firstlineno 的偏移量,而不是绝对位置。

【讨论】:

    猜你喜欢
    • 2012-01-03
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 1970-01-01
    • 2020-01-16
    • 2019-05-29
    • 2023-04-05
    • 1970-01-01
    相关资源
    最近更新 更多