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

4
我已经到处寻找,但我找不到一个使用元组(包含可选参数)和关键字的PyArg_ParseTupleAndKeywords()的示例。我发现最接近的是这个问题,但答案并不特别有用。大多数示例似乎将关键字作为可选参数,但似乎元组也应该能够包含可选参数。
假设我要解析以下参数:
  • 双精度数组的numpy数组(必填)
  • 双精度数组的numpy数组(可选,无关键字)
  • 可选的关键字参数:
    • k1 = > numpy数组中的双精度数组
    • k2 = >整数
    • k3 = >双精度浮点数
    • 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()的适当方法是什么?
2个回答

3
Python 3.3 及以后的版本,您可以在格式字符串中使用 $表示后面的参数只能使用关键字传递;Python 3.6 及以后的版本,您可以通过在 keywords 参数中使用空名称表示仅支持位置传递的参数。因此,在高版本的 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);

2
我认为下面的简化解决方案类似于您的情况,但是如果您有许多可选参数或更有趣的参数类型,它可能会变得很棘手。 我不确定是否有更好的解决方案,但我还没有找到。希望有一天会有人发布一个更清晰的解决方案。 在更复杂的解析场景中,您必须聪明地生成有用的参数解析错误消息。
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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接