📜  Python|在 C 中使用 Iterable 并诊断故障

📅  最后修改于: 2022-05-13 01:55:43.046000             🧑  作者: Mango

Python|在 C 中使用 Iterable 并诊断故障

本文旨在编写使用来自任何可迭代对象(例如列表、元组、文件或生成器)的项目的 C 扩展代码。

代码 #1:C 扩展函数,显示如何使用可迭代的项目。

static PyObject* py_consume_iterable(
    PyObject* self, PyObject* args)
{
    PyObject* obj;
    PyObject* iter;
    PyObject* item;
  
    if (!PyArg_ParseTuple(args, "O", &obj)) {
        return NULL;
    }
  
    if ((iter = PyObject_GetIter(obj)) == NULL) {
        return NULL;
    }
  
    while ((item = PyIter_Next(iter)) != NULL) {
        /* Use item */
        ... Py_DECREF(item);
    }
  
    Py_DECREF(iter);
    return Py_BuildValue("");
}

上面的代码反映了Python中的类似代码。 PyObject_GetIter()调用与调用iter()获取迭代器相同。 PyIter_Next()函数调用迭代器上的 next 方法,返回下一项,如果没有更多项,则返回 NULL。确保你小心内存管理—— Py_DECREF()需要在生成的项目和迭代器对象本身上调用以避免内存泄漏。诊断分段错误 –
解释器因分段错误、总线错误、访问冲突或其他致命错误而剧烈崩溃。人们喜欢获取Python回溯,以显示程序在发生故障时运行的位置。
faulthandler 模块可用于帮助您解决此问题。在您的程序中包含以下代码。

代码#2:

import faulthandler
faulthandler.enable()

或者,使用 -Xfaulthandler 选项运行Python ,例如:

bash % python3 -Xfaulthandler program.py

最后但同样重要的是,可以相应地设置 PYTHONFAULTHANDLER 环境变量。启用故障处理程序后,C 扩展中的致命错误将导致在失败时打印Python回溯。例如:

Fatal Python error: Segmentation fault
Current thread 0x00007fff71106cc0:
File "example.py", line 6 in foo
File "example.py", line 10 in bar
File "example.py", line 14 in spam
File "example.py", line 19 in 
Segmentation fault

虽然这不能说明 C 代码中哪里出了问题,但至少它可以说明它是如何从Python到达那里的。

故障处理程序将显示失败时执行的Python代码的堆栈回溯。至少,这将显示被调用的顶级扩展函数。借助pdb或其他Python调试器,可以调查导致错误的Python代码流。