Argparse and ArgumentDefaultsHelpFormatter. Formatting defaults when sys.stdin / stdout is selected by default

I am interested in using the formatting of the ArgumentDefaultsHelpFormatter class from argparse (my program has several subcommands). By default, input and output arguments are specified as sys.stdin and sys.stdout, respectively. However, formatting these two arguments can be a bit confusing for users (for example, (default: ', mode' r 'at 0x10028e0c0>). Is there a way to specifically and easily change the output format for these two arguments to something like "default: STDIN "or" default: STDOUT "?

thanks

import sys import argparse parser = argparse.ArgumentParser(prog='PROG', formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('--infile', '-i', metavar='File', help='The input file/stream.', default=sys.stdin, type=argparse.FileType('r'), required=False) parser.add_argument('--outfile', '-o', metavar='File', help='The output file/stream.', default=sys.stdout, type=argparse.FileType('r'), required=False) parser.add_argument('--whatever-arg', '-w', type=str, default='any', help='Change something', required=False) args = parser.parse_args() parser.print_help() 

What gives:

 usage: PROG [-h] [--infile File] [--outfile File] [--whatever-arg WHATEVER_ARG] optional arguments: -h, --help show this help message and exit --infile File, -i File The input file/stream. (default: <open file '<stdin>', mode 'r' at 0x10028e0c0>) --outfile File, -o File The output file/stream. (default: <open file '<stdout>', mode 'w' at 0x10028e150>) --whatever-arg WHATEVER_ARG, -w WHATEVER_ARG Change something (default: any) 
+5
source share
2 answers

You can subclass ArgumentDefaultsHelpFormatter to do what you want.

 from argparse import ArgumentDefaultsHelpFormatter,RawDescriptionHelpFormatter class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter): def _get_help_string(self, action): help = action.help if '%(default)' not in action.help: if action.default is not argparse.SUPPRESS: defaulting_nargs = [argparse.OPTIONAL, argparse.ZERO_OR_MORE] if action.option_strings or action.nargs in defaulting_nargs: if type(action.default) == type(sys.stdin): print action.default.name help += ' (default: ' + str(action.default.name) + ')' else: help += ' (default: %(default)s)' return help parser = argparse.ArgumentParser(prog='PROG', formatter_class=CustomFormatter) 

result for me:

 optional arguments: -h, --help show this help message and exit --infile File, -i File The input file/stream. (default: <stdin>) --outfile File, -o File The output file/stream. (default: <stdout>) --whatever-arg WHATEVER_ARG, -w WHATEVER_ARG Change something (default: any) 
+4
source

If you give default='-' instead of sys.stdin , the help display will be

 the input file/stream. (default: -) 

That is, help displays the default string, but FileType converts the '-' to stdin / out.

As shown in AH , you can configure the _get_help_string method. It doesn't matter which class you inherit, since modifying this method is all that ADHF does:

 class ArgumentDefaultsHelpFormatter(HelpFormatter): """... """ def _get_help_string(self, action): help = action.help if '%(default)' not in action.help: if action.default is not SUPPRESS: defaulting_nargs = [OPTIONAL, ZERO_OR_MORE] if action.option_strings or action.nargs in defaulting_nargs: help += ' (default: %(default)s)' return help 

Please note that all this modification adds a line to the help parameter - only (default: %(default)s)

This means that you can get a similar effect by adjusting your own help lines, for example.

 parser.add_argument('--infile', '-i', metavar='File', help='The input file/stream, (default: stdin).', default='-', type=argparse.FileType('r')) parser.add_argument('--whatever-arg', '-w', default='any', help='Change something, (default: %(default)s)') 

In other words, it saves the spelling (default: %(default)s) for your 28 arguments.

If you are not comfortable setting up the HelpFormatter class (although this is what developers recommend - with the appropriate caveats), you can customize your own setting. For example, create a simple helper function that adds an extra line to each help line:

 def foohelp(astr): return astr + ' (default: %(default)s)' arg1 = parser.add_argument('-f','--fooarg', help=foohelp('help string')) 

Speaking about changing the program programmatically, it is worth noting that add_argument creates an Action object. You can save a link to it, as I am here, and configure the settings.

 arg1 = parser.add_argument('-f','--fooarg', help='help string') print arg1.help arg1.help = foohelp(arg1.help) # modify help after creation print arg1.help 

With 30 arguments, you probably did a lot of copy-n-paste to define them, or write various helper functions to optimize your setup. Adding a default display is another of these tasks. You can do this during setup, or you can do it through a custom Formatter.

+2
source

Source: https://habr.com/ru/post/1239566/


All Articles