conditional args parse in python - python

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

Arguments in top level parser come before subparsers if it has subparsers

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.

Overwrite a default argument with another one using the command line

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)

argparse coexistsnce of required args and subparsers

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

Unable to assign default values to arguments in Python argparse

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')

argparse combine with optional parameter

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)

Categories

Resources