python argparse 在描述后打印使用文本

11 投票
4 回答
8592 浏览
提问于 2025-04-17 22:08

有没有办法在使用python argparse时,在描述文本后面打印使用说明文本?我已经让命令行的argparse正常工作了,但我想在使用信息之前打印版本信息。

编辑:

version: 1.0

usage: blahcmd [-h] [-help] 

some lovely help

4 个回答

0

这个解决方案可以在解析过程中捕获所有的标准输出和错误输出,具体可以参考这个链接

当没有输入或者输入“-h,--help”时,它会打印出自定义的命令,这个灵感来源于这个链接这个链接

try:
    _out = io.StringIO()
    _err = io.StringIO()
    with redirect_stdout(_out):
        with redirect_stderr(_err):
            ARG = parser.parse_args(sys.argv[1:] or ['--help'])
except SystemExit as err:
    print("This program does something awesome but you got it wrong.")
    #possibly parser.print_help()
    sys.stderr.write(_err.getvalue())
    sys.stdout.write(_out.getvalue())
    sys.exit(err.code)
3

一个简单的解决办法是把版本信息加到你的使用说明里。这不是最完美的办法(注意多了一个'usage'的文字),但算是一个开始。

In [64]: parser=argparse.ArgumentParser(description='description')
# 'usage' parameter just sets the 'usage' attribute
In [67]: parser.usage='version 1.0.1\n'+parser.format_usage()
In [68]: parser.print_help()
usage: version 1.0.1
usage: ipython [-h]

description

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

help中的内容顺序是由ArgumentParser.format_help这个方法决定的(引用自argparse.py文件):

def format_help(self):
    formatter = self._get_formatter()

    # usage
    formatter.add_usage(self.usage, self._actions,
                        self._mutually_exclusive_groups)

    # description
    formatter.add_text(self.description)

    # positionals, optionals and user-defined groups
    for action_group in self._action_groups:
        formatter.start_section(action_group.title)
        formatter.add_text(action_group.description)
        formatter.add_arguments(action_group._group_actions)
        formatter.end_section()

    # epilog
    formatter.add_text(self.epilog)

    # determine help from format above
    return formatter.format_help()

我可以想象写一个自定义的方法来添加你的版本信息,比如:

def format_help(self):
    formatter = self._get_formatter()

    # version info
    formatter.add_text('version 1.0.1')

    # usage
    formatter.add_usage(self.usage, self._actions,
                        self._mutually_exclusive_groups)
    ...

ipython中,这个函数可以正常工作:

In [74]: def format_help(parser):
    formatter=parser._get_formatter()
    formatter.add_text('version 1.0.1')
    formatter.add_usage(parser.usage, parser._actions, parser._mutually_exclusive_groups)
    formatter.add_text(parser.description)
    return formatter.format_help()
In [75]: print format_help(parser)
version 1.0.1

usage: ipython [-h]

description
5

这里有个不太优雅的解决办法(可以看看我在原问题下的评论):

你可以自己定义一个 HelpFormatter 的子类,然后在解析器中使用 formatter_class 选项来传递这个子类。这个子类可能需要重写 _format_usage 这个方法。不过,这种做法并不是特别推荐,因为定义自己格式化类的接口并没有公开。

from argparse import ArgumentParser, HelpFormatter
from gettext import gettext as _

class VersionedHelp(HelpFormatter):
    def _format_usage(self, usage, actions, groups, prefix=None):
        if prefix is None:
            prefix = _('Version: x.y\n\nusage: ')
        return HelpFormatter._format_usage(self, usage, actions, groups, prefix)

p = ArgumentParser(formatter_class=VersionedHelp)
p.parse_args()
9

argparse模块没有提供添加“前言”的选项。当你显示帮助信息时,它总是usage:开头。你能做的最好的事情就是在创建ArgumentParser时,使用usage参数来自定义使用说明文本,添加版本号:

import argparse

parser = argparse.ArgumentParser(usage='Any text you want\n')

请注意,帮助信息仍然会以usage:开头。

一个不太优雅的解决办法是让usage信息以\r开头:

>>> import argparse
>>> usage = '\r{}\nusage: %(prog)s etc.'.format('Version a b'.ljust(len('usage:')))
>>> parser = argparse.ArgumentParser(usage=usage)
>>> parser.parse_args(['-h'])
Version a b
usage:  etc.

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

我觉得这种使用\r的方法可能不太通用。可能有些终端不支持这个技巧。我已经用ljust调整了版本字符串,确保当这个技巧有效时,整个usage:字符串会消失,这样你就不会看到像v1.2e:这样的短版本字符串。

注意:你现在必须手动创建完整usage文本。

撰写回答