Python argparse 在类型之前检查选择

Sco*_*ott 5 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())
Run Code Online (Sandbox Code Playgroud)

这抛出:

$ 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')
Run Code Online (Sandbox Code Playgroud)

hpa*_*ulj 3

是的,在解析过程中,typethen 的choices顺序是明确且有意的(而不仅仅是偶然的)。当准备分配arg_stringsnamespace它时,它会调用_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
Run Code Online (Sandbox Code Playgroud)

在哪里_get_value应用该action.type函数并_check_value进行测试

value not in action.choices  
Run Code Online (Sandbox Code Playgroud)

对于解析choices只需响应in( __contains__) 表达式。

所以choices必须反映转换后的值。如果typeint,则choices=[1,2,3]正确,['1','2','3']否则不正确。

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

metavar是您替换不需要的choices列表的最强大的工具。我必须运行一个测试用例来看看它是否能解决所有 3 种情况的问题。