argparse:如何将选项映射到不同的值?

3
当使用argparse时,我希望用户可以从"choices"中选择,但是我希望他们的选择能够确定一个更复杂的值(类似于"store_const"的工作方式)。
例如,当从"smoker"状态中选择"['current', 'former', 'never']"时,我希望"current"映射到"Current every day smoker."。
有没有一种优雅的方法来实现这个功能?
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--smoker', choices=['current','former','never'])
print(vars(parser.parse_args()))

正常输出:

$ ./script.py --smoker current
{'smoker': 'current'}

希望达成的目标:

$ ./script.py --smoker current
{'smoker': 'Current every day smoker.'}

我以为可以使用lambda类型参数来实现,但是argparse强制执行选择列表:
choice_dict = {'current': 'Current everyday...'}
parser.add_argument('--smoker', type=lambda x: choice_dict[x], choices=choice_dict.keys())
print(vars(parser.parse_args()))

./script.py --smoker current
usage: script.py [-h] [--smoker {current}]
script.py: error: argument --smoker: invalid choice: 'Current everyday...' (choose from 'current')

3
我认为这不应该是您的参数解析器的责任,而应该由其他格式化所需输出的组件来处理。 - 0x5453
首先,将字符串传递给“type”,然后检查“choices”。您可以将“keys”作为选择项,但不要使用“type”。解析后,使用“choice_dict[args.smoker]”将键转换为值。 - hpaulj
你可以在 type 中进行转换,而不需要使用 choices。但是你将无法获得 help,并且可能需要调整错误类。 - hpaulj
1个回答

3
尽管我同意0x5452的评论,认为最好将此格式与解析器解耦,但是您可以使用一个Action来实现您想要的功能:
import argparse

CONVERSION_TABLE = {'current': 'Currently smokes',
                    'former': 'Used to smoke',
                    'never': 'Never smoke'}

class RenameOption(argparse.Action):
     def __call__(self, parser, namespace, values, option_string=None):
         setattr(namespace, self.dest, CONVERSION_TABLE[values])

parser = argparse.ArgumentParser()
parser.add_argument('--smoker', action=RenameOption, choices=CONVERSION_TABLE)
print(vars(parser.parse_args()))

结果如下:
$ python test.py --smoker current
{'smoker': 'Currently smokes'}

$ python test.py --smoker no
usage: test.py [-h] [--smoker {current,former,never}]
test.py: error: argument --smoker: invalid choice: 'no' (choose from 'current', 'former', 'never')

3
谢谢!这是对action=的巧妙运用。我最终使用了一个带有metavar定义的lambdaparser.add_argument('--smoker', type=lambda x: CONVERSION_TABLE[x], metavar=list(CONVERSION_TABLE.keys()) - semenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接