Reputation: 301
I have test scenario where I need to take action based on arguments passed to python script. The requirement is as follows:
test.py -a a1 -b b1 [[[-c c1] [-d d1]] | [-e e1 -f f1]]
The error could be generic error for all the optional arguments.
Till now, I'm trying to do it using parents=
option of argparse.ArgumentParser
but it is giving error when I try to read the passed arguments.
import argparse
parent_parser = argparse.ArgumentParser(add_help=False)
parent_parser.add_argument('-a', type=str, required=True)
parent_parser.add_argument('-b', type=str, required=True)
one_parser = argparse.ArgumentParser(parents=[parent_parser])
one_parser.add_argument('-c', type=str, default="test")
one_parser.add_argument('-d', type=str, default="Default")
multi_parser = argparse.ArgumentParser(parents=[parent_parser])
multi_parser.add_argument('-e', type=str)
multi_parser.add_argument('-f', type=str)
if str(one_parser.parse_args().c):
print(one_parser.parse_args())
elif str(multi_parser.parse_args().e):
print(multi_parser.parse_args())
When I run the script as :
test.py -a a1 -b b1 -e e1 -f f1
I'm getting the error :
usage: test.py [-h] -a A -b B [-c C] [-d D]
test.py: error: unrecognized arguments: -e e1 -f f1
Process finished with exit code 2
Any pointers are highly appreciated. Thank you.
Answer: The solution is hack but it worked for me.
import argparse
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-a', type=str, required=True)
parser.add_argument('-b', type=str, required=True)
parser.add_argument('-c', type=str)
parser.add_argument('-d', type=str)
parser.add_argument('-e', type=str)
parser.add_argument('-f', type=str)
args = parser.parse_args()
a = str(args.a)
b = str(args.b)
c = str(args.c)
d = str(args.d)
e = str(args.e)
f = str(args.f)
if (e != "None" and f == "None") or (e == "None" and f != "None"):
if c == "None" and d == "None":
raise argparse.ArgumentTypeError("Both e and f arguments are required")
elif c != "None" or d != "None":
raise argparse.ArgumentTypeError("e and f are not supported with c or d")
if (c != "None" or d != "None") and (e != "None" or f != "None"):
raise argparse.ArgumentTypeError("c and d are not supported with e and f")
if e == "None" and f == "None":
if c == "None":
c = "test"
if d == "None":
d = "Default"
IMO, argparser should handle argument dependency more efficiently. Maybe someone will contribute and help us all.. :)
Upvotes: 2
Views: 1766
Reputation: 520
Your issue is using multiple parser, arguments groups might help you.
You then have to check yourself that arguments comply with your conditions, and raise argparse.ArgumentError when necessary.
Here is a code sample that could do the trick. The arguments_group serve only to document the -h parameter (argparser help)
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-a", required=True)
parser.add_argument("-b", required=True)
first = parser.add_argument_group("group 1", "None, one or both")
first.add_argument("-c")
first.add_argument("-d")
second = parser.add_argument_group("group 2", "None or both")
second.add_argument("-e")
second.add_argument("-f")
args = parser.parse_args()
a = args.a
b = args.b
c = args.c
d = args.d
e = args.e
f = args.f
if (e is not None and f is None) or (e is None and f is not None):
if c is None and d is None:
raise argparse.ArgumentError("Both e and f arguments are required")
elif c is None or d is not None:
raise argparse.ArgumentError("e and f are not supported with c or d")
if (c is not None or d is not None) and (e is not None or f is not None):
raise argparse.ArgumentError("c and d are not supported with e and f")
Upvotes: 1