11

Is there a way to print usage text after the description text with python argparse? I have my cmd line argparse working, but i would like to print version info before usage info.

Edit:

version: 1.0

usage: blahcmd [-h] [-help] 

some lovely help
2
  • Please show us an example of what you want to do. Commented Mar 13, 2014 at 15:00
  • One fairly ugly option is to define your own subclass of HelpFormatter to pass to the parser with the formatter_class option. Your subclass would probably want to override the _format_usage method. This isn't entirely recommended, since the interface for defining your own formatting class was never made public. Commented Mar 13, 2014 at 15:17

5 Answers 5

9

The argparse module does not provide any option to add a "prolog". When the help is displayed it always start with usage:. The best you can do is to customize the usage text adding the version number, using the usage parameter when you instantiate the ArgumentParser:

import argparse

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

Note that the help will still start with usage:.

A dirty workaround that might work is to start the usage message with a \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

I don't think that this usage of \r is portable. There are probably some terminals where this trick doesn't work. I've ljusted the version string to make sure that when the trick works, the whole usage: string disappears from string and you don't get things like v1.2e: when using short version strings.

Note: you must manually create the whole usage text now.

Sign up to request clarification or add additional context in comments.

Comments

5

Here's an ugly hack (see my comment on the original question):

Define your own subclass of HelpFormatter to pass to the parser with the formatter_class option. The subclass should probably override the _format_usage method. This isn't entirely recommended, since the interface for defining your own formatting class was never made public.

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()

3 Comments

I was writing the same thing, when I noticed that this naive solution doesn't work properly because the help starts with usage: anyway.
Old answer replaced with a completely different ugly hack :)
Thanks for that! I was going to try something similar and I don't think your hack was so ugly -- even if relies on an undocumented API. BTW, I've submitted an edit to include the explanation from your comment (which I hadn't seen until after I looked more carefully).
3

A rough solution is to add the version text to your usage line. It's not perfect (note the extra 'usage' text), but its a start

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

The order of components in the help are determined by the ArgumentParser.format_help method (quoting from the argparse.py file):

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()

I can imagine writing a custom method that adds your version information, e.g.

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)
    ...

In ipython this function works:

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

Comments

0

This solution captures all stdout stderr output during parsing, see this.

On no input as well as on "-h,--help" it will print custom command, inspired by this and this.

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)

Comments

-1

To have additional text, e.g., version info, before the usage line you could simply put a print() command before argparser. The main description will still be after the usage line as in the example to the question.

import argparse

print('version 1.0')
parser = argparse.ArgumentParser(description="description: some lovely help")
parser.parse_args()

prints:

version 1.0
usage: prog_name.py [-h]

description: some lovely help

options:
  -h, --help  show this help message and exi

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.