我檢查的類型的用戶輸入,像這樣獲得一個PyObjectType的字符串表示:在Pythonç提高時類型錯誤擴展
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;
}
很抱歉的混亂;我的意思是要求可以應用於任何PyObject的通用解決方案,而不一定是元組。然而,你讓我想,爲什麼不繼續這樣下去:'PyArg_ParseTuple(Py_BuildValue(「(o)」,「s」,&out))' - 你怎麼看? –
我認爲(但我不是100%肯定)['PyArg_Parse'](https://docs.python.org/2/c-api/arg.html#c.PyArg_Parse)可以採用元組或者一個參數(基於它被設計使用的舊函數調用方法的描述)。我還沒有測試過 – DavidW