I would like to have a code that get the first argument as tool and after that expects different options depending on the tool
myapp.py [TOOL] [TOOLPARAMETERS]
python myapp.py tool0 -i 'path/to/my_image.jpg' -o 'path/to/my_output_path_folder/' -r 0.7 -m 13
python myapp.py tool1 -m 3 -r 'some_string_now' -m 13
As you can see in this case each tool could have it's own required arguments and in each case they could even expect different types
I have been messing around with add_subparsers with some success.
import argparse
parser = argparse.ArgumentParser(prog='myapp', usage='%(prog)s [tool] [options]')
parser.add_argument('-a', required=True, help='required globally argument for all tools')
subparsers = parser.add_subparsers(help='tool help')
# subparser for tool0
parser_tool0 = subparsers.add_parser('tool0', help='tool 0 help')
# ADD tool0 ARGUMENTS
parser_tool0.add_argument('-i' , required=True, help='path to the input folder')
parser_tool0.add_argument('-o' , required=True, help='path to the output folder')
parser_tool0.add_argument('-r' , default=0.7, type=float, help='some float')
parser_tool0.add_argument('-g' , default=10, type=int, help='some integrer')
parser_tool0.add_argument('-d' , default=False, help='debug')
# subparser for tool1
parser_tool0 = subparsers.add_parser('tool1', help='tool 0 help')
# ADD tool0 ARGUMENTS
parser_tool0.add_argument('-r' , help='r not required string')
parser_tool0.add_argument('-f' , required=True, help='f not required string')
parser_tool0.add_argument('-d' , default=0.7, type=float, help='some float')
parser_tool0.add_argument('-i' , default=10, type=int, help='some integrer')
parser_tool0.add_argument('-b' , default=False, help='boolean')
parser_tool0.add_argument('opts',
help='Modify config options using the command-line',
default=None, nargs=argparse.REMAINDER)
args = parser.parse_args()
print(args)
So I would like to know what should be the best practices for that case.
Thanks in advance
Per the docs and this so answer subparsers are the way to go.
Related
I have this MRE:
import argparse
parser = argparse.ArgumentParser(description='Bundle a Python application')
parser.add_argument(
'-o', '--output', metavar='OUTPUT FILE', dest='file_name', type=str,
default=None)
parser.add_argument(
'--extensions', '--ext', action='store_const', metavar='EXTENSIONS',
dest='extensions', const=True, default=False,
help='Whether to allow the importing of C extensions (not needed if C extensions are optional')
if 0:
actions_parser = parser.add_subparsers(
dest='action', metavar='ACTION', help='Action mod should take')
actions_parser.required = True
build_parser = actions_parser.add_parser("build")
build_parser.add_argument(
dest='root', metavar='PROJECT', type=str, help='Project path',
nargs='?', default='.')
get_parser = actions_parser.add_parser("get")
get_parser.add_argument(
dest='module', metavar='MODULE', type=str, help='Module to download')
args = parser.parse_args()
If you run this with python test.py --ext, this works as expected.
However, if you change the 0 to a 1, then python test.py foo --ext fails, even though it should work. Why?
As it turns out, all the arguments attached to the main parser must be before any subaction, e.g. python test.py --ext foo.
can anyone help me to overwrite a default argument with another one passing through the command line ?
this is my code:
parser = argparse.ArgumentParser()
parser.add_argument('log', action='store', help='path to the log file')
parser.add_argument('-f', '--filter', default =['filter.json'], help='path to a filter file')
parser.add_argument('-w', '--waiver', type =list, default = [], action='append', help='path to a waiver file')
args = parser.parse_args()
this is the command line to be used:
python3 script.py -f filter_file -w waiver_file log_file
so, I need to overwrite this default =['filter.json'] with filter_file
But don't know what should I do, can you support please ?
thanks
Your script is working:
My output:
PS C:\Users\xf01145\Documents\Python> & "C:/Program Files/Python37/python.exe"
c:/Users/xf01145/Documents/Python/cli.py log.log -f bla.bla blubb.bla test.test hugo.txt
Namespace(filter=['bla.bla', 'blubb.bla', 'test.test', 'hugo.txt'], log='log.log', waiver=[])
0 bla.bla
1 blubb.bla
2 test.test
3 hugo.txt
PS C:\Users\xf01145\Documents\Python>
from this:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('log', action='store', help='path to the log file')
parser.add_argument('-f', '--filter', default =['filter.json'], help='path to a filter file', nargs='+')
parser.add_argument('-w', '--waiver', type =list, default = [], action='append', help='path to a waiver file')
args = parser.parse_args()
print(args)
for i,item in enumerate(args.filter):
print(i, item)
Problem: I have a parser that has 1 required arg and a subparser that accepts 3 args of which 2 are required when that sub parser is invoked
As follows
Code:
parser.add_argument("-f", "--foo", type=str, required=True, help="foo help")
subparsers=parser.add_subparsers(help="Sub parsers")
mysubparser = subparsers.add_parser("a", help="a subparser")
mysubparser.add_argument("-b", "--bar", type=str, required=True, help="bar help")
mysubparser.add_argument("-bz", "--baz", type=str, required=True, help="baz help")
mysubparser.add_argument("-bzg", "--bazinga", action="store_true", help="bazinga help")
What I tried:
my problem is that
python myscript.py -f "hi" a -b "hi" -bz "hi" works but python myscript.py a -b "hi" -bz "hi" -f "hi" doesn't. Do required args have to be specified first? I think it looks a bit clunky the first way. is there a way this can be fixed?
I want both versions to work. Or a better alternative to doing things this way
I am using Python argparse to take in parameters through the CLI. I have tried using the following but when I don't give any one of the arguments, it gives the output as None. I want then default ones to be the ones provided in const=. Please take a look.
parser = argparse.ArgumentParser()
parser.add_argument('--input', nargs='?', const='testInput')
parser.add_argument('--target', nargs='?', const='testTarget')
parser.add_argument('--msg', nargs='?', const='helloFromTheOtherSide')
args = parser.parse_args()
print args.input
If I don't give input, it prints it as None as I said. I want it to print TestInput instead..
Use the default argument:
parser = argparse.ArgumentParser()
parser.add_argument('--input', nargs='?', default='testInput')
parser.add_argument('--target', nargs='?', default='testTarget')
parser.add_argument('--msg', nargs='?', default='helloFromTheOtherSide')
args = parser.parse_args()
print args.input
With
parser.add_argument('--input', nargs='?', default='testInput', const='aConst')
you have a 3 way choice
prog # input='testInput'
prog --input # input='aConst'
prog --input myfile # input='myfile'
If you don't need that aConst option, omit the nargs='?'. Since it is a flagged argument it is already optional. It doesn't need the `?'.
parser.add_argument('--input', default='testInput')
If the user use the optional parameter -o then the user has to use parameter -b as well.
However, the -b parameter you have to use only if the user set the parameter -o.
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-f', nargs='?', required=True)
parser.add_argument('-o', nargs='?', required=False)
parser.add_argument('-b', nargs='?', required=????)
args = parser.parse_args()
How is it possible to solve this problem?
Add a test after args = parser.parse_args():
if args.o and not args.b:
print >> sys.stderr, 'The -b option is required whenever -o is specified'
sys.exit(1)