在类型之前的Python argparse检查选项

时间:2016-04-07 14:53:08

标签: python argparse

我试图让用户传入一个函数名称。出于某种原因,似乎argparse在检查选择之前执行类型检查/转换。这是一个错误吗?最好的办法吗?

import argparse

def foo():
  return 'foo'

def bar():
  return 'bar'

parser = argparse.ArgumentParser()
functions = {f.__name__:f for f in [foo, bar]}
parser.add_argument("function", type=lambda f: functions.get(f), help="which function", choices=functions)
args = parser.parse_args()
print(args.function())

这引发:

$ python blah.py foo
usage: blah.py [-h] {foo,bar}
blah.py: error: argument function: invalid choice: <function foo at 0x7f65746dd848> (choose from 'foo', 'bar')

2 个答案:

答案 0 :(得分:2)

是的,在解析type时,choices订单是明确且有意的(而不仅仅是附带的)。在准备将arg_strings分配给namespace时,它会调用_get_values,这样做:

  def _get_values(self, action, arg_strings)
        .... (various nargs tests)
        value = self._get_value(action, arg_string)
        self._check_value(action, value)
        return value

其中_get_value适用action.type函数和_check_value测试

value not in action.choices  

要解析choices,只需回复in__contains__)表达式。

因此choices必须反映转化后的值。如果typeint,那么choices=[1,2,3]是正确的,['1','2','3']不是。

在选择的显示上存在一些(很大程度上未解决的)错误问题。长列表,例如range(100)可以解析,但不能很好地显示。并且显示还要求choices可迭代(例如列表,元组,字典)。此显示问题会影响使用情况,帮助和错误消息(每种格式choices略有不同)。

metavar是您用来替换不受欢迎的choices列表的最强大工具。我必须运行一个测试用例来查看它是否能解决所有这三种情况。

答案 1 :(得分:1)

显然,你可以通过O(b ^ m)作为选择来解决这个问题,例如。

functions.keys()

但是,如果要提供此类接口(将函数映射到命令行参数),您可能需要查看click