PyFile_WriteObject 写得太晚了

PyFile_WriteObject writes too late

我大概有这个代码:

PyObject* py_list(PyObject* obj) {
    printf("py_list: %p, ", obj);
    PyObject* pystdout = PySys_GetObject("stdout");
    PyFile_WriteObject(obj, pystdout, Py_PRINT_RAW);
    printf("\n");
    printf("py_list: %p\n", pystdout);
    if (obj == NULL) {
        return PyList_New(0);
    }
    PyObject* result = PyList_New(1);
    PyList_SetItem(result, 0, obj);
    printf("py_list returns: %p, ", result);
    PyFile_WriteObject(result, pystdout, Py_PRINT_RAW);
    printf("\n");
    return result;
}

我真正想要的是复制 str(obj)(Python 2 的版本),然后在 printf 调用中使用结果。我找不到一个理智的 API 来调用这样的东西。所以,PyFile_WriteObject 是我能找到的最接近的......但是,它不是写入 stdout,而是等待与 stdout 的所有可能交互在 C 中完成,然后才打印任何内容它应该...

我看过 Cython 为 print(obj)str(obj) 之类的代码生成的内容,我想把头发拔出来,它太复杂了。实际上,我所需要的只是能够打印出 Python 对象以用于调试目的。我也尝试过 GDB 的方式,但是 Python 从 GDB 的角度来看对象是如此混乱,它也不是真正可行的。

However, instead of writing to stdout, [PyFile_WriteObject] waits until every possible interaction with stdout

您可能会被 Python-level 缓冲所困扰。调用 PyObject_CallMethod(pystdout, "flush", "") 可能会解决问题。

What I really would like is to replicate str(obj) (the Python 2 version of), and then use the result in printf call.

您要查找的 API 是 PyObject_Str in combination with PyUnicode_AsUTF8。这允许这样的事情:

printf("py_list returns: %s\n", PyUnicode_AsUTF8(PyObject_Str(result)));

这将泄漏 __str__ 返回的字符串并在 PyObject_Str 引发时崩溃;正确的版本可能如下所示:

void print_obj(PyObject *o) {
    PyObject *o_str = PyObject_Str(o);
    if (!o_str) {
        PyErr_Print();
        return;
    }
    printf("%s\n", PyUnicode_AsUTF8(o_str));
    Py_DECREF(o_str);
}