argparse位置参数配nargs='*'设列表默认值报Invalid Choice如何解决
问题原因
这是argparse本身的实现特性:当位置参数配置nargs='*'时,argparse在校验默认值时会把整个默认列表作为单个候选值和choices列表比对,而不会遍历校验列表内的每个元素,因此会把默认的[1,3,5]判定为非法值。位置参数与可选参数对nargs='*'的默认值校验逻辑不同,这也是你使用非位置参数配置时不会触发该问题的原因。
可行解决方案
方案1:解析后手动赋值默认值(最简洁易用)
先把参数的默认值设为None,关闭argparse对默认值的choices校验,参数解析完成后手动补充默认值即可,用户传入的参数仍然会正常触发逐个校验逻辑,不影响原有校验规则:
from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument( "choices", nargs="*", type=int, choices=[1,2,3,4,5], default=None ) if __name__ == "__main__": args = parser.parse_args() # 手动补充默认值 if args.choices is None: args.choices = [1,3,5] print(args.choices)
方案2:自定义Action实现内置默认值处理
如果希望所有逻辑都在参数定义阶段完成,可以继承argparse.Action自定义参数处理逻辑,在校验阶段单独处理默认值的校验规则:
from argparse import ArgumentParser, Action class DefaultListAction(Action): def __call__(self, parser, namespace, values, option_string=None): if not values: values = [1,3,5] setattr(namespace, self.dest, values) parser = ArgumentParser() parser.add_argument( "choices", nargs="*", type=int, choices=[1,2,3,4,5], action=DefaultListAction ) if __name__ == "__main__": print(parser.parse_args().choices)
内容的提问来源于stack exchange,提问作者David Davó
相关产品推荐
相关产品推荐

