Python argparse使用标志正确格式化选项参数

Python argparse使用标志正确格式化选项参数,python,formatting,posix,argparse,Python,Formatting,Posix,Argparse,我正在尝试使用Python的argparse为“choice”类型的命令行参数创建格式良好的帮助消息。对于命令,我允许名称'--operation'和别名'-o'。当前,argparse正在打印帮助消息中两个选项旁边的选项列表 请注意,这个问题与格式化选项的帮助消息的问题不同(Anthon在这里给出了一个很好的答案:) 选项列表重复两次是非常笨拙的。特别是因为我会有更长的列表。我认为最好是这样: -o, --operation {create,update,delete} 这当然是假设没有关于

我正在尝试使用Python的argparse为“choice”类型的命令行参数创建格式良好的帮助消息。对于命令,我允许名称'--operation'和别名'-o'。当前,argparse正在打印帮助消息中两个选项旁边的选项列表

请注意,这个问题与格式化选项的帮助消息的问题不同(Anthon在这里给出了一个很好的答案:)

选项列表重复两次是非常笨拙的。特别是因为我会有更长的列表。我认为最好是这样:

-o, --operation {create,update,delete}
这当然是假设没有关于如何工作的POSIX规则。我想没有


我怎样才能达到预期的输出?还是有一个很好的理由让我不去尝试呢?

这是一个很好的尝试,但似乎没有一个好的地方可以去尝试

定义您自己的格式化程序,它覆盖(基本上通过复制)
\u format\u action\u调用
方法。您要做的唯一更改是仅将选项添加到最后一个选项字符串中

class MyHelpFormatter(HelpFormatter):

    def _format_action_invocation(self, action):
        if not action.option_strings:
            default = self._get_default_metavar_for_positional(action)
            metavar, = self._metavar_formatter(action, default)(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 = self._get_default_metavar_for_optional(action)
                args_string = self._format_args(action, default)
                for option_string in action.option_strings[:-1]:
                    parts.append('%s' % (option_string,))
                parts.append('%s %s' % (action.option_strings[-1], args_string)
            return ', '.join(parts)

这是一个相当好的黑客行为,但似乎没有一个好的地方来钩住它

定义您自己的格式化程序,它覆盖(基本上通过复制)
\u format\u action\u调用
方法。您要做的唯一更改是仅将选项添加到最后一个选项字符串中

class MyHelpFormatter(HelpFormatter):

    def _format_action_invocation(self, action):
        if not action.option_strings:
            default = self._get_default_metavar_for_positional(action)
            metavar, = self._metavar_formatter(action, default)(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 = self._get_default_metavar_for_optional(action)
                args_string = self._format_args(action, default)
                for option_string in action.option_strings[:-1]:
                    parts.append('%s' % (option_string,))
                parts.append('%s %s' % (action.option_strings[-1], args_string)
            return ', '.join(parts)

您可能需要检查或打包另一种方法是使用
metavar
选项
替换为较短的字符串,并将
选项
显示为
帮助
表达式的一部分。您可能需要检查或打包另一种方法是使用
metavar
选项
替换为较短的字符串,并将
选项
显示为
帮助
表达式的一部分。您已经接近了。不幸的是,您的简化导致了两个问题:(1)action.narg可以是None,这就是为什么它们会==0而不是>0(尽管这似乎是错误的代码!)和(2)您现在删除了所有打印选项,而不仅仅是复制。我将投赞成票,这与我问题中的另一个链接很好地配合。但代码本身就有缺陷,所以我认为我不能接受。我已经让它在我这边运行了。刚刚为第一个问题添加了“action.nargs不是None,action.nargs>0”,并添加了“parts[-1]+self.\u format_args(action,default)”,以修复第二个问题。我将更新。愚蠢的我,看起来我没有先发布更长、正确的答案,所以我不能就这么做。你很接近。不幸的是,您的简化导致了两个问题:(1)action.narg可以是None,这就是为什么它们会==0而不是>0(尽管这似乎是错误的代码!)和(2)您现在删除了所有打印选项,而不仅仅是复制。我将投赞成票,这与我问题中的另一个链接很好地配合。但代码本身就有缺陷,所以我认为我不能接受。我已经让它在我这边运行了。刚刚为第一个问题添加了“action.nargs不是None,action.nargs>0”,并添加了“parts[-1]+self.\u format_args(action,default)”,以修复第二个问题。我将更新。愚蠢的我,看起来我没有先发布更长的、正确的答案,所以我不能只是回滚到它。
class MyHelpFormatter(HelpFormatter):

    def _format_action_invocation(self, action):
        if not action.option_strings:
            default = self._get_default_metavar_for_positional(action)
            metavar, = self._metavar_formatter(action, default)(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 = self._get_default_metavar_for_optional(action)
                args_string = self._format_args(action, default)
                for option_string in action.option_strings[:-1]:
                    parts.append('%s' % (option_string,))
                parts.append('%s %s' % (action.option_strings[-1], args_string)
            return ', '.join(parts)