【问题标题】:howto parse required mutually exclusive argument in python C-api如何在python C-api中解析所需的互斥参数
【发布时间】:2019-01-18 10:29:51
【问题描述】:

如何使用 python C-api 解析一组必需但互斥的参数?

例如给定函数定义

static PyObject* my_func(PyObject *self, PyObject *args, PyObject *kwargs)  {
   double a;          // first argument, required 
   double b=0, c=0;   // second argument, required but mutually exclusive, b is default keyword if no keyword is set
   char d[] = "...";  // third argument, optional

   // parse arguments
   ...
}

我的想法是两次解析输入参数,即将上面的...替换为:

   static const char *kwList1[] = {"a","b","c","d"};
   static const char *kwList2[] = {"a","b","d"};
   int ret;
   if (!(ret = PyArg_ParseTupleAndKeywords(args,kwargs,"d|dds",(char **)kwList1,&a,&b,&c,&d))) {
      ret = PyArg_ParseTupleAndKeywords(args,kwargs,"d|ds",(char **)kwList2,&a,&b,&d));
   }
   if (!ret) return NULL;

   // verify that one of, but not both, variables b and c are non-zero
   ...

但是,对PyArg_ParseTupleAndKeywords() 的第二次调用返回 0 表示有效输入,因此我在这里假设变量 argskwargs 具有由第一次调用 PyArg_ParseTupleAndKeywords() 设置的一些属性,这会导致第二次调用失败(输出python错误为:TypeError: a float is required)。

我知道可以使用argparse python 模块解决上述问题,但更喜欢直接使用 C-api 的解决方案。这里的一个想法是,如果可以将输入argskwargs 复制到两个新的PyObject 变量中,并在第二次调用PyArg_ParseTupleAndKeywords() 时使用它们,但是我找不到任何api-这样做的功能(我想我还需要知道如何释放为此分配的内存)。

【问题讨论】:

    标签: python c arguments mutual-exclusion


    【解决方案1】:

    似乎问题在于第一次调用PyArg_ParseTupleAndKeywords() 设置了错误指示器,导致第二次调用函数失败。所以解决方案是在对PyArg_ParseTupleAndKeywords() 的调用之间插入对PyErr_Clear() 的调用。总而言之,以下代码执行任务

    static PyObject* my_func(PyObject *self, PyObject *args, PyObject *kwargs)  {
       double a;          // first argument, required 
       double b=0, c=0;   // second argument, required but mutually exclusive, b is default keyword if no keyword is set
       char d[] = "...";  // third argument, optional
    
       // parse arguments
       static const char *kwList1[] = {"a","b","c","d"};
       static const char *kwList2[] = {"a","b","d"};
       int ret;
       if (!(ret = PyArg_ParseTupleAndKeywords(args,kwargs,"d|dds",(char **)kwList1,&a,&b,&c,&d))) {
          PyErr_Clear();
          ret = PyArg_ParseTupleAndKeywords(args,kwargs,"d|ds",(char **)kwList2,&a,&b,&d));
       }
       if (!ret) return NULL;
    
       // verify that one of, but not both, variables b and c are non-zero
       if (b==0 && c==0) {
          PyErr_SetString(PyExc_TypeError,"Required mutually exclusive arguments 'b' or 'c' (pos 2) not found (or input with value 0)");
          return NULL;
       } else if (b!=0 && c!=0) {
          PyErr_SetString(PyExc_TypeError,"Use of multiple mutually exclusive required arguments 'b' and 'c' (pos 2)");
          return NULL;
       }
    
       ...
    
    }
    

    再一次,这并不能防止使用参数bc 调用函数,因为其中一个是0,另一个不是。不过这是个小问题。

    【讨论】:

      猜你喜欢
      • 2012-05-25
      • 1970-01-01
      • 1970-01-01
      • 2017-07-02
      • 2020-07-29
      • 2017-01-03
      • 1970-01-01
      • 2013-03-16
      • 1970-01-01
      相关资源
      最近更新 更多