我正在调用一个函数,该函数需要一个位置参数列表,后跟关键字参数。我想分别处理args和kwargs。不幸的是,与用于位置参数的PyArg_ParseTuple不同,没有用于关键字参数的等效PyArg_ParseKeywords。我试图通过传递Py_None(也为NULL)代替args来防止解析位置参数:
static PyObject* test_func(PyObject* self, PyObject* args, PyObject *kwargs)
{
static const char *kwList[] = {"kw1", "kw2", NULL};
const char* kw1_val = NULL;
PyObject* kw2_val = NULL;
if (! PyArg_ParseTupleAndKeywords(Py_None,
kwargs,
"zO",
const_cast<char**>(kwList),
&kw1_val,
&kw2_val))
{
return NULL;
}
}
具有Py_None(或NULL)会导致:
Python/getargs.c:1390: bad argument to internal function
如果我用args代替Py_None,则会出现以下错误:
TypeError: function takes at most 2 arguments (4 given)
上面的TypeError发生了,因为它解包了我传递给test_func的2个位置args和2个关键字args,而只有两个变量kw1_val和kw2_val可以在解析方法中接收这4个值。
有没有办法处理上述情况?请注意,位置参数可以具有任意数量的值。
尝试传递一个空的元组而不是Py_None
:
static PyObject* test_func(PyObject* self, PyObject* args, PyObject *kwargs)
{
static const char *kwList[] = {"kw1", "kw2", NULL};
const char* kw1_val = NULL;
PyObject* kw2_val = NULL;
PyObject *retvalue = NULL;
PyObject *empty = PyTuple_New(0);
if (empty == NULL){
goto out;
}
if (! PyArg_ParseTupleAndKeywords(empty,
kwargs,
"zO",
const_cast<char**>(kwList),
&kw1_val,
&kw2_val))
{
goto out;
}
// other code here
out:
Py_XDECREF(empty);
return retvalue;
}
我认为您在这里遇到了经典的X-Y问题。不用担心,我有同一个。
这里的Y是PyArg_ParseTupleAndKeywords
,实际上X只是“在Python C API中仅解析kwargs
”。
kwargs
这只是一个Python dict()
,因此,实际上,如果我们不在乎位置参数,我们可以使用现有的C API函数来处理dict()
,PyDict_*
family of functions。 >
因此,如果我们有原型的PyDict_*
:
PyCFunction
[我们知道在Python 2和Python 3中
PyObject* Amit(PyObject *self, PyObject *args, PyObject *keywds);
都是keywds
。因此我们可以例如这个:
PyDict
[
PyObject* layerp = NULL; if (keywds != NULL) layerp = PyDict_GetItemString(keywds, "layer");
将返回PyDict_GetItemString
而不会设置错误,因此我们只需检查NULL
是否为layerp
,就可以知道是否有可选的关键字参数。