Search code examples
pythonargparse

What is the best way to customize help formatter for argparse.ArgumentParser


I am using argparse.ArgumentParser to parse arguments and output help text. I want to show the default values for all options and also set the width of the output. My current solution seems a bit of a hack. Can someone suggest a better way to approach this? My current approach is to define a subclass of argparse.ArgumentDefaultsHelpFormatter and then modify the width property in __init__. Any thoughts on something cleaner?

# help class to set width of help to wrap at terminal width
class MyHelpFormatter(argparse.ArgumentDefaultsHelpFormatter):
    columns = -1

    def __init__(self, *args, **kwargs):
        if MyHelpFormatter.columns == -1:
            try:
                MyHelpFormatter.columns = os.get_terminal_size().columns
                if 'width' not in kwargs:
                    kwargs['width'] = MyHelpFormatter.columns
            except OSError:
                # not in a terminal
                pass
        super().__init__(*args, **kwargs)


# instantiate argument parser
parser = argparse.ArgumentParser(description='program description',
                                 formatter_class=MyHelpFormatter)

Solution

  • In the end, because of the verbosity, I created a simple python file called argparser.py (notice the extra 'r'), put it in my python path, and now I just use that instead of argparse.

    '''
    Extension to argparse to show default values for arguments and
    print out help at proper width on screen.  Basically, it just adds the
    MyHelpFormatter to the constructor for the argparse.ArgumentParser
    class.
    
    Example usage:
    -------------------
    import argparser
    
    parser = argparser.ArgumentParser(description="Find and deal with autosave file")
    parser.add_argument('-n', '--newer', type=int, default=0, help='how many days back to go, 0->forever')
    args = parser.parse_args()
    -------------------
    
    Running this with -h would produce:
    
    usage: <progname>.py [-h] [-n NEWER]
    
    Find and deal with autosave file
    
    optional arguments:
      -h, --help            show this help message and exit
      -n NEWER, --newer NEWER
                            how many days back to go, 0->forever (default: 0)
    
    '''
    
    
    import argparse
    import os
    import sys
    
    if sys.version_info[0] < 3:
        raise RuntimeError('Need python3 or greater to use argparser.py')
    
    
    class MyHelpFormatter(argparse.ArgumentDefaultsHelpFormatter):
        columns = -1
    
        def __init__(self, *args, **kwargs):
            if MyHelpFormatter.columns == -1:
                try:
                    MyHelpFormatter.columns = os.get_terminal_size().columns
                    if 'width' not in kwargs:
                        kwargs['width'] = MyHelpFormatter.columns
                except OSError:
                    # not in a terminal
                    pass
            super().__init__(*args, **kwargs)
    
    
    class ArgumentParser(argparse.ArgumentParser):
        def __init__(self, *args, **kwargs):
            kwargs['formatter_class'] = MyHelpFormatter
            super().__init__(*args, **kwargs)