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)
Related
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.
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)
Setting the parents argument with a parser will allow for sharing common arguments between parsers (e.g. parents and sub-commands). But, applying a base parser to both the parent and sub-command appears to overwrite the value from the parent parser with the value from the sub-command parser when using an argument that has specified the value attribute to with a dest keyword, whether or not the invocation has specified the argument in the sub-command.
How can I use argparse module to merge the options in the parent and the sub-command (i.e. store the value if either parser contains the option, use the default if neither parser specifies the option, and it doesn't matter how to handle if both parsers specify the option)?
sample.py:
from argparse import ArgumentParser
parser = ArgumentParser(add_help=False) # The "base"
parser.add_argument('-v', '--verbose', dest='verbose', action='store_true')
parser.add_argument('-d', '--dir', dest='dir', default=None)
parser_main = ArgumentParser(parents=[parser])
subparsers = parser_main.add_subparsers(dest='command')
subparsers.add_parser('cmd1', parents=[parser])
args = parser_main.parse_args()
print(str(args))
Then, in the shell:
> sample.py -v -d abc
Namespace(command=None, dir='abc', verbose=True)
> sample.py -v cmd1 -d abc
Namespace(command='cmd1', dir='abc', verbose=False)
> sample.py -d abc cmd1 -v
Namespace(command='cmd1', dir=None, verbose=True)
> sample.py cmd1 -v -d abc
Namespace(command='cmd1', dir='abc', verbose=True)
Using SUPPRESS for the subparser default keeps it from overwriting the parent parser value. A SUPPRESS default is not inserted into the namespace at the start of parsing. A value is written only if the user used that argument.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-f', '--foo', default='foobar')
parser.add_argument('-v', '--verbose', action='store_const', default=False, const=True)
sp = parser.add_subparsers(dest='cmd')
sp1 = sp.add_parser('cmd1')
sp1.add_argument('-f', '--foo', default=argparse.SUPPRESS)
sp1.add_argument('-v', '--verbose', action='store_const', default=argparse.SUPPRESS, const=True)
args = parser.parse_args()
print(args)
sample runs:
1833:~/mypy$ python3 stack62904585.py
Namespace(cmd=None, foo='foobar', verbose=False)
1834:~/mypy$ python3 stack62904585.py --foo FOO -v
Namespace(cmd=None, foo='FOO', verbose=True)
1834:~/mypy$ python3 stack62904585.py cmd1
Namespace(cmd='cmd1', foo='foobar', verbose=False)
1834:~/mypy$ python3 stack62904585.py -v cmd1 -f bar
Namespace(cmd='cmd1', foo='bar', verbose=True)
The patch that last changed this behavior (2014)
https://bugs.python.org/issue9351 argparse set_defaults on subcommands should override top level set_defaults
also https://bugs.python.org/issue27859
You can store the value in different attributes by specifying different names with the dest keyword:
from argparse import ArgumentParser
parser = ArgumentParser(add_help=False) # The "base"
parser.add_argument('-v', '--verbose', dest='verbose', action='store_true')
parser.add_argument('-d', '--dir', dest='dir', default=None)
parser_main = ArgumentParser()
parser_main.add_argument('-v', '--verbose', dest='g_verbose', action='store_true')
parser_main.add_argument('-d', '--dir', dest='g_dir', default=None)
subparsers = parser_main.add_subparsers(dest='command')
subparsers.add_parser('cmd1', parents=[parser])
args = parser_main.parse_args()
verbose = args.verbose or args.g_verbose if hasattr(args, 'verbose') else args.g_verbose
d = (args.g_dir if args.dir is None else args.dir) if hasattr(args, 'dir') else args.g_dir
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')