Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/468.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python C扩展中引发类型错误时获取PyObjectType的字符串表示形式_Python_Python 2.7_Python C Api_Python C Extension - Fatal编程技术网

在Python C扩展中引发类型错误时获取PyObjectType的字符串表示形式

在Python C扩展中引发类型错误时获取PyObjectType的字符串表示形式,python,python-2.7,python-c-api,python-c-extension,Python,Python 2.7,Python C Api,Python C Extension,我正在检查用户输入的类型,如下所示: PyObject *key = PyTuple_GetItem(tuple, 0); if (!PyObject_TypeCheck(key, &PyBaseString_Type) { PyErr_SetString(PyExc_TypeError, "Key must be str"); return NULL; } 但是,在异常消息中,我希望包括用户提交的错误类型,以使调试更容易 有没有一种简单或惯用的方法来实现这一点 我能

我正在检查用户输入的类型,如下所示:

PyObject *key = PyTuple_GetItem(tuple, 0);
if (!PyObject_TypeCheck(key, &PyBaseString_Type) {
    PyErr_SetString(PyExc_TypeError, "Key must be str");
    return NULL;
}
但是,在异常消息中,我希望包括用户提交的错误类型,以使调试更容易

有没有一种简单或惯用的方法来实现这一点


我能想到的唯一办法是:

PyObject *key = PyTuple_GetItem(tuple, 0);
if (!PyObject_TypeCheck(key, &PyBaseString_Type) {
    // This returns a new reference which must be Py_DECREFed
    PyObject *bad_type_string = PyObject_Str((PyObject *)key->ob_type);
    char *bad_type_char = PyString_AsString(bad_type_string);
    PyErr_Format(PyExc_TypeError, "Key must be str, not %s", bad_type_char);
    Py_DECREF(bad_type_string);
    return NULL;
}
我想我可以将其包装在宏中:

# define CHECK_TYPE(expr, name, input) \
    do {    \
        if (!(expr)) {
            PyObject *bad_type_string = PyObject_Str((PyObject *)input->ob_type);  \
            char *bad_type_char = PyString_AsString(bad_type_string); \
            PyErr_Format(PyExc_TypeError, "%s must be str, not %s", name bad_type_char); \
            Py_DECREF(bad_type_string); \
            goto error; \
        }
    } while (0);
并且这样使用:

static PyObject *foo(PyObject *self, PyObject *args) {
    // ...
    PyObject *key = PyTuple_GetItem(tuple, 0);
    CHECK_TYPE(PyObject_TypeCheck(key, &PyBaseString_Type, 'key', key);
    // ...
error:
    return NULL;
}
你可以稍微误用一下。稍微有点不整洁的是,它输出为
常量char*
,因此您也必须从元组中获取该项

const char* out;
if (!PyArg_ParseTuple(tpl,"s", &out)) {
    return NULL;
} else {
    key = PyTuple_GetItem(tpl,0); /* borrowed - remember to incref */
}
这会产生类似于

TypeError:必须是str,而不是int


注意:这对于Python2很好,因为
“s”
同时匹配
str
unicode
对象(即有效地
基串
)。对于Python3,它只接受
str
(而不是
bytes
),因此您可能必须遵循和“将
O&
格式与
PyUnicode\u FSConverter()
一起用作转换器”。这会导致以下错误:

TypeError:无法将“int”对象隐式转换为str


此外,它还有一点更好,因为
out
是一个
PyBytesObject
,您可以直接使用它,而不必执行
PyTuple\u GetItem

抱歉造成混淆;我的意思是要求一个通用的解决方案,可以应用于任何PyObject,而不一定是tuple。然而,你让我思考,为什么不继续这样做:
PyArg\u ParseTuple(Py\u BuildValue(“(o)”,“s”,&out))
-你认为呢?我认为(但我不是100%确定)可以接受一个元组或一个参数(基于它设计用于的旧函数调用方法的描述)。我还没有测试过这个