对于argparse选择,是否有一种干净的方式为每个选择写一个单行帮助?

时间:2016-05-07 22:43:14

标签: python argparse

使用python argaparse" choices"默认帮助如下所示:

>>> parser.add_argument('move', choices=['rock', 'paper', 'scissors'])

positional arguments:
  {rock,paper,scissors}

如果明确如何选择一个,那么哪个有效呢?但如果每个选择都需要自己的迷你帮助,那么效果不是很好。

有没有办法以干净的方式为每个选择写一行帮助,这些都是这样的:

parser.add_argument("action",
                    choices=[
                        ["status", help="Shows current status of sys"],
                        ["load", help="Load data in DB"],
                        ["dump", help="Dump data to csv"],
                    ],

2 个答案:

答案 0 :(得分:3)

argparse不支持此格式。这是我的解决方案。这不好,但它确实有效。

from argparse import ArgumentParser, RawTextHelpFormatter

choices_helper = { "status": "Shows current status of sys",
                   "load": "Load data in DB",
                   "dump": "Dump data to csv"}

parser = ArgumentParser(description='test', formatter_class=RawTextHelpFormatter)    
parser.add_argument("action",
                    choices=choices_helper,
                    help='\n'.join("{}: {}".format(key, value) for key, value in choices_helper.iteritems()))

尝试使用Sub-commands(subparsers)是更好的主意。

答案 1 :(得分:0)

@ julivco的回答产生了这个帮助:

In [20]: parser.print_help()
usage: ipython3 [-h] {load,status,dump}

test

positional arguments:
  {load,status,dump}  load: Load data in DB
                      status: Shows current status of sys
                      dump: Dump data to csv

optional arguments:
  -h, --help          show this help message and exit

argparse choices的处理非常简单。它使用value in choices进行测试,并遍历它以构造{...}字符串。有一些bug /问题正在考虑改进字符串格式,但没有人要求/建议这种帮助格式化。

====================

这是一个自定义的Action子类。它的行为与通常的store相同,但借用了subparser Action类中的格式化创意。它希望choices是一个字典(可以很容易地更改为列表或元组列表)。

class NewAction(argparse._StoreAction):
    class _ChoicesPseudoAction(argparse.Action):
        # from _SubParsersAction
        def __init__(self, name, aliases, help):
            metavar = dest = name
            if aliases:
                metavar += ' (%s)' % ', '.join(aliases)
            sup = super(NewAction._ChoicesPseudoAction, self)
            sup.__init__(option_strings=[], dest=dest, help=help,
                         metavar=metavar)

    def make_help(self):
        # build list used for help display
        self._choices_actions = []    
        for key in self.choices:        
            help = choice_dict[key]
            choice_action = self._ChoicesPseudoAction(key, [], help)
            self._choices_actions.append(choice_action)

    def _get_subactions(self):
        # called by HelpFormater
        return self._choices_actions

choice_dict = { "status": "Shows current status of sys",
            "load": "Load data in DB",
            "dump": "Dump data to csv"}

parser = argparse.ArgumentParser()
a = parser.add_argument('--foo', action=NewAction, choices=choice_dict, help='choices help')
a.make_help()

parser.print_help()
print(parser.parse_args('--foo status'.split()))
print(parser.parse_args())

输出如下:

2028:~/mypy$ python3 stack37094448.py --foo test
usage: stack37094448.py [-h] [--foo {load,dump,status}]

optional arguments:
  -h, --help            show this help message and exit
  --foo {load,dump,status}
                        choices help
    load                Load data in DB
    dump                Dump data to csv
    status              Shows current status of sys
Namespace(foo='status')
usage: stack37094448.py [-h] [--foo {load,dump,status}]
stack37094448.py: error: argument --foo: invalid choice: 'test' (choose from 'load', 'dump', 'status')