Python argparse如何将choices选项映射为自定义目标值
argparse选项值映射实现方案
首先说明之前写法失效的核心原因:
argparse处理参数的顺序是先执行
type指定的类型转换,再校验转换后的值是否在choices范围内,所以你用lambda做转换后,转换得到的长文本不在原始choices列表里,自然会触发校验报错。
有两种非常简洁优雅的实现方式,可以根据使用场景选择:
方案1:解析后手动映射(最直白,适合小脚本)
不需要修改argparse的任何参数配置,等参数解析完成后统一做值替换即可,逻辑零门槛,不会出任何兼容问题:
import argparse # 先定义值映射关系 smoker_map = { 'current': 'Current every day smoker.', 'former': 'Former smoker.', 'never': 'Never smoker.' } parser = argparse.ArgumentParser() parser.add_argument('--smoker', choices=smoker_map.keys()) args = parser.parse_args() # 解析完成后直接替换映射值 args.smoker = smoker_map[args.smoker] print(vars(args))
这个方案下argparse原生的错误提示、帮助信息都不会受任何影响,任何人看代码都能立刻懂逻辑。
方案2:自定义Action(最规范,适合复用场景)
如果需要映射的参数比较多,或者希望映射逻辑完全封装在参数定义阶段,可以自定义argparse的Action类,完全符合argparse的原生扩展设计:
import argparse smoker_map = { 'current': 'Current every day smoker.', 'former': 'Former smoker.', 'never': 'Never smoker.' } # 自定义映射动作 class MapChoiceAction(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): # values是用户输入的、已经通过choices校验的原始值,直接做映射赋值 setattr(namespace, self.dest, smoker_map[values]) parser = argparse.ArgumentParser() parser.add_argument( '--smoker', choices=smoker_map.keys(), action=MapChoiceAction ) print(vars(parser.parse_args()))
这个方案的使用体验和原生参数完全一致:用户输错参数时会正常提示可选值列表,-h帮助信息也能正常展示可选输入项,不需要在解析后写额外的转换逻辑。
两种方案运行./script.py --smoker current都会输出期望结果:
{'smoker': 'Current every day smoker.'}
内容的提问来源于stack exchange,提问作者semenko
相关产品推荐
相关产品推荐

