我正在尝试使用户能够传递函数名称。由于某种原因,似乎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')

最佳答案

是的,在解析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必须在转换后反射(reflect)值。如果typeint,则choices=[1,2,3]是正确的,而['1','2','3']不正确。

在选择项的显示上存在一些(大部分 Unresolved )错误问题。长名单,例如range(100)可用于解析,但显示效果不佳。并且显示还要求choices是可迭代的(例如,列表,元组,字典)。此显示问题会影响用法,帮助和错误消息(每种格式的choices略有不同)。
metavar是用于替换不良choices列表的最强大的工具。我必须运行一个测试用例,以查看它是否可以解决所有3种情况。

关于Python argparse在输入之前检查选择,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36479850/

10-11 04:21