在调用PyArg_ParseTupleAndKeywords时如何仅解析'kwargs'并跳过args?

问题描述 投票:3回答:2

我正在调用一个函数,该函数需要一个位置参数列表,后跟关键字参数。我想分别处理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个值。

有没有办法处理上述情况?请注意,位置参数可以具有任意数量的值。

python python-c-api
2个回答
2
投票

尝试传递一个空的元组而不是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;
}

0
投票

我认为您在这里遇到了经典的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,就可以知道是否有可选的关键字参数。

© www.soinside.com 2019 - 2024. All rights reserved.