python argparse中帮助消息的选项值语法

时间:2013-05-03 22:09:17

标签: python python-2.7 argparse

我正在尝试使用argparse,python来获取--set=X=Y之类的参数。第一种方法是:

parser.add_argument('--set', dest='d', metavar='book=from:to', action='append', type=str, required=True, help='...')

我必须自己拆分结果(X=Y),但这没关系。 我的问题是关于argparse生成的帮助消息(--help)的语法。它使用了可能更常见的语法--set X=Y,结果如下:

--set book=from:to  ...

有没有办法让我改变这种行为,所以帮助看起来像:

--set=book=from:to  ...

2 个答案:

答案 0 :(得分:0)

不,不是没有创建自己的argparse.HelpFormatter()类的自定义子类。

这需要替换该类的内部私有方法。当前实现使用此方法:

def _format_action_invocation(self, action):
    if not action.option_strings:
        metavar, = self._metavar_formatter(action, action.dest)(1)
        return metavar

    else:
        parts = []

        # if the Optional doesn't take a value, format is:
        #    -s, --long
        if action.nargs == 0:
            parts.extend(action.option_strings)

        # if the Optional takes a value, format is:
        #    -s ARGS, --long ARGS
        else:
            default = action.dest.upper()
            args_string = self._format_args(action, default)
            for option_string in action.option_strings:
                parts.append('%s %s' % (option_string, args_string))

        return ', '.join(parts)

注意parts.append('%s %s' % (option_string, args_string));您必须提供自己的上述方法版本,并将空格替换为=等号。

执行此操作的问题在于,argparse库的未来版本完全在其使用不同方法名称的权利范围内,从而破坏了您的自定义类。

答案 1 :(得分:0)

为避免上述解决方案的大部分“未来合规性”问题,另一种方法是装饰_format_action_invocation。当然,如果argparse方法更改其名称也不会中断,但至少它允许方法中的argparse代码更新,并避免了代码重复。

作为奖励,以下解决方案还允许更改使用情况行中的帮助程序,以保持使用情况和调用部分之间的一致性:

import re

def deco_argparse_format_action(func, is_invoc=False):
    def wrapper_format_action(*args, **kwargs):
        '''
        Replaces `-f FOO' or  '--foo FOO` by resp. `-f=FOO` and `--foo=FOO` in argparse helper.
        Although there is always possibility to use either `--foo FOO` or
        `--foo=FOO`, it is sometimes better to document the '=' way
        rather than the ' ' way.
        For example, when the option argument contains special characters like '-'
        it must be expressed with '=' in order to not confuse the shell that executes
        the command line.
        '''
        string = func(*args, **kwargs)
        if is_invoc is True:
            # 'invocation section' case
            patt = r"(-+[^ ,]+) +"
            repl = r"\1="
        else:
            # 'usage section' case
            patt = r"(\[-+[^ \]]+) +([^|])"
            repl = r"\1=\2"

        return re.sub(patt,repl,string)
    return wrapper_format_action

用法:

import argparse

#-- Customize helper for options with arguments
#   (print '-f=FOO, --foo=FOO' instead of '-f FOO, --foo FOO')
HelpFormatter._format_action_invocation = deco_argparse_format_action(
        HelpFormatter._format_action_invocation,
        is_invoc = True,
        )

HelpFormatter._format_actions_usage = deco_argparse_format_action(
        HelpFormatter._format_actions_usage,
        )