Python 如何使用PyArg_ParseTupleAndKeywords解析包含可选参数和关键字的元组?

Python 如何使用PyArg_ParseTupleAndKeywords解析包含可选参数和关键字的元组?,python,python-2.7,numpy,Python,Python 2.7,Numpy,我到处都找过,但找不到与元组(包含可选参数)和关键字一起使用的PyArg_ParseTupleAndKeywords()示例。我找到的最接近的答案是,但答案并不是特别有用。大多数示例似乎将关键字作为可选参数,但元组似乎也应该能够包含可选参数 假设我试图解析以下参数: 双精度numpy数组(必需) 双精度整数数组(可选,无关键字) 可选关键字参数: k1=>numpy双精度数组 k2=>整数 k3=>double k4=>Python类实例 看来我应该做点什么 static PyObjec

我到处都找过,但找不到与元组(包含可选参数)和关键字一起使用的
PyArg_ParseTupleAndKeywords()
示例。我找到的最接近的答案是,但答案并不是特别有用。大多数示例似乎将关键字作为可选参数,但元组似乎也应该能够包含可选参数

假设我试图解析以下参数:

  • 双精度numpy数组(必需)
  • 双精度整数数组(可选,无关键字)
  • 可选关键字参数:
    • k1=>numpy双精度数组
    • k2=>整数
    • k3=>double
    • k4=>Python类实例
看来我应该做点什么

static PyObject* pymod_func(PyObject* self, PyObject* args, PyObject* kwargs) {
  static char* keywords[] = {"k1", "k2", "k3", "k4", NULL};

  PyObject *arg1, *arg2, *k1, *k4
  PyObject *arr1, *arr2, *karr1;
  double *k3;
  int *k2;
  PyArg_ParseTupleAndKeywords(args, kwargs, "O!|O!OidO", keywords, &arg1, &PyArray_Type, &arg2, &PyArray_Type, &k1, &PyArray_Type, &k2, &k3, &k4);

  arr1 = PyArray_FROM_OTF(arg1, NPY_FLOAT64, NPY_ARRAY_INOUT_ARRAY);
  if (arr1 == NULL) return NULL;

  arr2 = PyArray_FROM_OTF(arg1, NPY_FLOAT64, NPY_ARRAY_INOUT_ARRAY);
  // no null check, because optional

  karr1 = PyArray_FROM_OTF(k1, NPY_FLOAT64, NPY_ARRAY_INOUT_ARRAY);
  // again, no null check, because this is optional

  // do things with k3, k2, and k4 also

  return NULL;
}
其他我看过的地方,但没有找到太多帮助:


使用
PyArg_ParseTupleAndKeywords()
的合适方法是什么?

我认为类似于下面的简化解决方案应该适用于您的场景,但如果您有许多可选的arg或更有趣的arg类型,它可能会变得糟糕。 我不确定是否有更好的解决方案,但我还没有找到。希望有一天有人会发布一个更干净的解决方案

您必须聪明地生成有用的arg解析错误消息 在更复杂的解析场景中

static PyObject* nasty_func(PyObject* self, PyObject* args, PyObject* kwargs) {
  static char* keywords[] = {"one", "optional", "two", NULL};
  static char* keywords_alt[] = {"one", "two", NULL};

  int ok = 0;
  PyObject *result = NULL;

  int *one;
  char *two;
  int *optional;

  ok = PyArg_ParseTupleAndKeywords(args, kwargs, "iis", keywords, &one, &optional, &two);

  if (!ok) {
    PyErr_Clear();
    ok = PyArg_ParseTupleAndKeywords(args, kwargs, "is", keywords_alt, &one, &two);
    if (!ok) {
      PyErr_SetString(PyExc_TypeError, "Invalid args. allowed formats: 'one:i, two:s' or 'one:i, optional:i, two:s'");
      return NULL;
    }
  }

  // do stuff with your parsed variables

  return result;
}

从Python 3.3开始,您可以在格式字符串中使用
$
,从Python 3.6开始,您可以在
关键字
参数中使用空名称

因此,在足够高版本的Python中,可以使用如下代码:

static char* keywords[] = {"", "", "k1", "k2", "k3", "k4", NULL};

// [...]

PyArg_ParseTupleAndKeywords(args, kwargs,
                            "O!|O!$O!idO", keywords,
                            &PyArray_Type, &arg1, &PyArray_Type, &arg2,
                            &PyArray_Type, &k1, &k2, &k3, &k4);