Given the following code snippet:
import argparse
import sys
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help="subcommand help")
command1 = subparsers.add_parser("foo", description="Run foo subcommand")
command2 = subparsers.add_parser("bar", description="Run bar subcommand")
opts = parser.parse_args(sys.argv[1:])
When I print help for this I get this:
usage: test.py [-h] {foo,bar} ...
positional arguments:
{foo,bar} subcommand help
optional arguments:
-h, --help show this help message and exit
Is there a way to make it print something like this instead:
usage: test.py [-h] {foo,bar} ...
subcommands:
foo Run foo subcommand
bar Run bar subcommand
optional arguments:
-h, --help show this help message and exit
without supplying a custom formatter? If I change the formatter then it also changes everything else about how the help is printed, but in my case I just want to change the way that subcommand help is printed from the parent (sub)command.
You need to set the help parameter, not the description parameter, to get the output you desire:
import argparse
import sys
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help="subcommand help")
command1 = subparsers.add_parser("foo", help="Run foo subcommand")
command2 = subparsers.add_parser("bar", help="Run bar subcommand")
opts = parser.parse_args(sys.argv[1:])
Output:
usage: test.py [-h] {foo,bar} ...
positional arguments:
{foo,bar} subcommand help
foo Run foo subcommand
bar Run bar subcommand
optional arguments:
-h, --help show this help message and exit
The argparse docs have this to say about the help value:
The help value is a string containing a brief description of the argument. When a user requests help (usually by using -h or --help at the command line), these help descriptions will be displayed with each argument.
And this to say to about the description value:
This argument gives a brief description of what the program does and how it works. In help messages, the description is displayed between the command-line usage string and the help messages for the various arguments.
Related
Consider this arg_test.py script:
#!/usr/bin/env python3
import argparse
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help='subcommand help')
# create the parser for subcommand
parser_a = subparsers.add_parser('do-stuff', help='Help for do-stuff subcommand')
args = parser.parse_args()
With the help for the subcommand I get:
./arg_test.py do-stuff -h
usage: arg_test.py do-stuff [-h]
optional arguments:
-h, --help show this help message and exit
How can I add some usage description when using -h? For example I would like to get:
./arg_test.py do-stuff -h
usage: arg_test.py do-stuff [-h]
This subcommand does awsome stuff << HOW DO I ADD THIS?
optional arguments:
-h, --help show this help message and exit
I'm trying to write a script that would take some flags and files as arguments and then execute other scripts, depend on the flag that the user chooses. For example, the command line should look like that:
main_script.py -flag1 -file_for_flag_1 another_file_for_flag_1
and
main_script.py -flag2 -file_for_flag_2
I tried to use the argparse library, but I don't know how to take the input files as arguments for the next steps and manipulate them as I want. I started with:
parser = argparse.ArgumentParser(description="Processing inputs")
parser.add_argument(
"-flat_map",
type=str,
nargs="+",
help="generates a flat addressmap from the given files",
)
parser.add_argument(
"-json_convert",
type=str,
nargs="+",
help="generates a flat addressmap from the given files",
)
args = parser.parse_args(args=["-flat_map"])
print(args)
I printed args in the end to see what I get from it but I got nothing I can work with.
Would like to have some guidance. Thanks.
You can convert the args to a dict (where the key is the arg option and the value is the arg value) if it's more convenient for you:
args_dict = {key: value for key, value in vars(parser.parse_args()).items() if value}
Using argparse you can use sub-commands to select sub-modules:
import argparse
def run_command(parser, args):
if args.command == 'command1':
# add code for command1 here
print(args)
elif args.command == 'command2':
# add code for command2 here
print(args)
parser = argparse.ArgumentParser(
prog='PROG',
epilog="See '<command> --help' to read about a specific sub-command."
)
subparsers = parser.add_subparsers(dest='command', help='Sub-commands')
A_parser = subparsers.add_parser('command1', help='Command 1')
A_parser.add_argument("--foo")
A_parser.add_argument('--bar')
A_parser.set_defaults(func=run_command)
B_parser = subparsers.add_parser('command2', help='Command 2')
B_parser.add_argument('--bar')
B_parser.add_argument('--baz')
B_parser.set_defaults(func=run_command)
args = parser.parse_args()
if args.command is not None:
args.func(parser, args)
else:
parser.print_help()
This generates a help page like so:
~ python args.py -h
usage: PROG [-h] {command1,command2} ...
positional arguments:
{command1,command2} Sub-commands
command1 Command 1
command2 Command 2
optional arguments:
-h, --help show this help message and exit
See '<command> --help' to read about a specific sub-command.
and help text for each sub-command:
~ python args.py B -h
arg.py command2 -h
usage: PROG command2 [-h] [--bar BAR] [--baz BAZ]
optional arguments:
-h, --help show this help message and exit
--bar BAR
--baz BAZ
Extremely nitpicky question, but it annoys me that the default argparse help message is a sentence fragment. For example, for a script that contains
#!/usr/bin/env python
import argparse
parser = argparse.ArgumentParser()
parser.parse_args()
The -h and --help flag message shows:
$ tmp.py --help
usage: tmp.py [-h]
optional arguments:
-h, --help show this help message and exit
However I prefer complete sentences in documentation and "sentence case" for headers:
$ tmp.py --help
Usage: tmp.py [-h]
Optional arguments:
-h, --help Show this help message and exit.
How can I keep the behavior of script -h and script --help but change the message?
Welp found the answer 5 seconds later.
#!/usr/bin/env python
import argparse
parser = argparse.ArgumentParser(add_help=False)
parser.parse_args()
parser.add_argument(
'-h', '--help', action='help', help='Show this help message and exit.')
Defining your own action='help' argument is probably the best answer. But it is possible to edit the default help.
All the defined Actions are collected in the parser._actions list. Yes, it is marked hidden, but people do access it as needed. Normally the help action is the first one created (as default), so it is element [0] of that list.
In [15]: parser._actions[0].help
Out[15]: 'show this help message and exit'
In [16]: parser._actions[0].help = "Show this help message and exit."
testing:
In [17]: parser.print_help()
usage: ipython3 [-h] {mySubcommand,m} ...
positional arguments:
{mySubcommand,m} sub-command help
mySubcommand (m)
Subcommand help
optional arguments:
-h, --help Show this help message and exit.
def main():
parser = argparse.ArgumentParser()
# specific file
parser.add_argument('-f', '--file', type=str, default='file',
help=Fore.BLUE + '--file access_log -extract-ip' + Style.RESET_ALL)
# http get file
parser.add_argument('-hgf', '--http-get-file', type=str, default='http-get-file',
help=Fore.BLUE + '--http-get-file URL' + Style.RESET_ALL)
I have a program where I tried to put help in my code using argparse:
import argparse,sys
parser = argparse.ArgumentParser(description='prog desc')
parser.add_argument('path', help='name of directory')
args = parser.parse_args()
parser.print_help()
this prints:
>python testArgs.py
usage: testArgs.py [-h] path
testArgs.py: error: too few arguments
but I'm expecting same as if I entered -h:
>python testArgs.py -h
usage: testArgs.py [-h] path
prog desc
positional arguments:
path name of directory
optional arguments:
-h, --help show this help message and exit
But if I switch the position of the print_help() before parse_args(), then it works right:
import argparse,sys
parser = argparse.ArgumentParser(description='prog desc')
parser.add_argument('path', help='name of directory')
parser.print_help()
args = parser.parse_args()
output:
>python testArgs.py
usage: testArgs.py [-h] path
prog desc
positional arguments:
path name of directory
optional arguments:
-h, --help show this help message and exit
usage: testArgs.py [-h] path
testArgs.py: error: too few arguments
What am I doing wrong?
In your first example your program doesn't reach the parser.print_help() method, it fails on parser.parse_args(), prints the default error message (which is testArgs.py: error: too few arguments) and exits the program.
In your second example, when you switch between the functions, it still behaves the same but you see the help details because you called the print_help() function before the program fails (you can see it fails because it still prints the error message at the end).
If you want to print the help message when an argparse error occurred, read this post:
Display help message with python argparse when script is called without any arguments
While using argparse, the help dialog of my program displays dest variable. How do I remove this?
I tried the add_help=False object but that just removed the help dialog for that option entirely.
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--interface", dest="interface", help="foo")
parser.add_argument("-m", "--mac", dest="mac", help="bar")
I get the following result with INTERFACE and MAC next to my optional arguments:
usage: test.py [-h] [-i INTERFACE] [-m MAC]
optional arguments:
-h, --help show this help message and exit
-i INTERFACE, --interface INTERFACE
foo
-m MAC, --mac MAC bar
How can I remove DEST values from my output?
As #hpaulj suggested, you can set the metavar parameter of each argument to an empty string
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--interface", dest="interface", help="foo", metavar='')
parser.add_argument("-m", "--mac", dest="mac", help="bar", metavar='')
parser.parse_args()
which will output the following result:
usage: test.py [-h] [-i] [-m]
optional arguments:
-h, --help show this help message and exit
-i , --interface foo
-m , --mac bar
Let me know if that's the output you expected.