The Python Oracle

How to insert newlines on argparse help text?

--------------------------------------------------
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Cool Puzzler LoFi

--

Chapters
00:00 How To Insert Newlines On Argparse Help Text?
00:42 Accepted Answer Score 586
01:10 Answer 2 Score 104
02:18 Answer 3 Score 44
02:55 Answer 4 Score 16
05:06 Answer 5 Score 12
06:39 Thank you

--

Full question
https://stackoverflow.com/questions/3853...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #argparse

#avk47



ACCEPTED ANSWER

Score 598


Try using RawTextHelpFormatter to preserve all of your formatting:

from argparse import RawTextHelpFormatter
parser = ArgumentParser(description='test', formatter_class=RawTextHelpFormatter)

It's similar to RawDescriptionHelpFormatter but instead of only applying to the description and epilog, RawTextHelpFormatter also applies to all help text (including arguments).




ANSWER 2

Score 104


If you just want to override the one option, you should not use RawTextHelpFormatter. Instead subclass the HelpFormatter and provide a special intro for the options that should be handled "raw" (I use "R|rest of help"):

import argparse

class SmartFormatter(argparse.HelpFormatter):

    def _split_lines(self, text, width):
        if text.startswith('R|'):
            return text[2:].splitlines()  
        # this is the RawTextHelpFormatter._split_lines
        return argparse.HelpFormatter._split_lines(self, text, width)

And use it:

from argparse import ArgumentParser

parser = ArgumentParser(description='test', formatter_class=SmartFormatter)

parser.add_argument('-g', choices=['a', 'b', 'g', 'd', 'e'], default='a',
    help="R|Some option, where\n"
         " a = alpha\n"
         " b = beta\n"
         " g = gamma\n"
         " d = delta\n"
         " e = epsilon")

parser.parse_args()

Any other calls to .add_argument() where the help does not start with R| will be wrapped as normal.

This is part of my improvements on argparse. The full SmartFormatter also supports adding the defaults to all options, and raw input of the utilities description. The full version has its own _split_lines method, so that any formatting done to e.g. version strings is preserved:

parser.add_argument('--version', '-v', action="version",
                    version="version...\n   42!")



ANSWER 3

Score 44


Another easy way to do it is to include textwrap.

For example,

import argparse, textwrap
parser = argparse.ArgumentParser(description='some information',
        usage='use "python %(prog)s --help" for more information',
        formatter_class=argparse.RawTextHelpFormatter)

parser.add_argument('--argument', default=somedefault, type=sometype,
        help= textwrap.dedent('''\
        First line
        Second line
        More lines ... '''))

In this way, we can avoid the long empty space in front of each output line.

usage: use "python your_python_program.py --help" for more information

Prepare input file

optional arguments:
-h, --help            show this help message and exit
--argument ARGUMENT
                      First line
                      Second line
                      More lines ...



ANSWER 4

Score 16


I've faced similar issue (Python 2.7.6). I've tried to break down description section into several lines using RawTextHelpFormatter:

parser = ArgumentParser(description="""First paragraph 

                                       Second paragraph

                                       Third paragraph""",  
                                       usage='%(prog)s [OPTIONS]', 
                                       formatter_class=RawTextHelpFormatter)

options = parser.parse_args()

And got:

usage: play-with-argparse.py [OPTIONS]

First paragraph 

                        Second paragraph

                        Third paragraph

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

So RawTextHelpFormatter is not a solution. Because it prints description as it appears in source code, preserving all whitespace characters (I want to keep extra tabs in my source code for readability but I don't want to print them all. Also raw formatter doesn't wrap line when it is too long, more than 80 characters for example).

Thanks to @Anton who inspired the right direction above. But that solution needs slight modification in order to format description section.

Anyway, custom formatter is needed. I extended existing HelpFormatter class and overrode _fill_text method like this:

import textwrap as _textwrap
class MultilineFormatter(argparse.HelpFormatter):
    def _fill_text(self, text, width, indent):
        text = self._whitespace_matcher.sub(' ', text).strip()
        paragraphs = text.split('|n ')
        multiline_text = ''
        for paragraph in paragraphs:
            formatted_paragraph = _textwrap.fill(paragraph, width, initial_indent=indent, subsequent_indent=indent) + '\n\n'
            multiline_text = multiline_text + formatted_paragraph
        return multiline_text

Compare with the original source code coming from argparse module:

def _fill_text(self, text, width, indent):
    text = self._whitespace_matcher.sub(' ', text).strip()
    return _textwrap.fill(text, width, initial_indent=indent,
                                       subsequent_indent=indent)

In the original code the whole description is being wrapped. In custom formatter above the whole text is split into several chunks, and each of them is formatted independently.

So with aid of custom formatter:

parser = ArgumentParser(description= """First paragraph 
                                        |n                              
                                        Second paragraph
                                        |n
                                        Third paragraph""",  
                usage='%(prog)s [OPTIONS]',
                formatter_class=MultilineFormatter)

options = parser.parse_args()

the output is:

usage: play-with-argparse.py [OPTIONS]

First paragraph

Second paragraph

Third paragraph

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