I have done as much research as possible but I haven't found the best way to make certain cmdline arguments necessary only under certain conditions, in this case only if other arguments have been given. Here's what I want to do at a very basic level:
p = argparse.ArgumentParser(description='...') p.add_argument('--argument', required=False) p.add_argument('-a', required=False) # only required if --argument is given p.add_argument('-b', required=False) # only required if --argument is given
From what I have seen, other people seem to just add their own check at the end:
if args.argument and (args.a is None or args.b is None): # raise argparse error here
Is there a way to do this natively within the argparse package?
I've been searching for a simple answer to this kind of question for some time. All you need to do is check if '--argument'
is in sys.argv
, so basically for your code sample you could just do:
import argparse import sys if __name__ == '__main__': p = argparse.ArgumentParser(description='...') p.add_argument('--argument', required=False) p.add_argument('-a', required='--argument' in sys.argv) #only required if --argument is given p.add_argument('-b', required='--argument' in sys.argv) #only required if --argument is given args = p.parse_args()
This way required
receives either True
or False
depending on whether the user as used --argument
. Already tested it, seems to work and guarantees that -a
and -b
have an independent behavior between each other.
You can implement a check by providing a custom action for --argument
, which will take an additional keyword argument to specify which other action(s) should become required if --argument
is used.
import argparse class CondAction(argparse.Action): def __init__(self, option_strings, dest, nargs=None, **kwargs): x = kwargs.pop('to_be_required', []) super(CondAction, self).__init__(option_strings, dest, **kwargs) self.make_required = x def __call__(self, parser, namespace, values, option_string=None): for x in self.make_required: x.required = True try: return super(CondAction, self).__call__(parser, namespace, values, option_string) except NotImplementedError: pass p = argparse.ArgumentParser() x = p.add_argument("--a") p.add_argument("--argument", action=CondAction, to_be_required=[x])
The exact definition of CondAction
will depend on what, exactly, --argument
should do. But, for example, if --argument
is a regular, take-one-argument-and-save-it type of action, then just inheriting from argparse._StoreAction
should be sufficient.
In the example parser, we save a reference to the --a
option inside the --argument
option, and when --argument
is seen on the command line, it sets the required
flag on --a
to True
. Once all the options are processed, argparse
verifies that any option marked as required has been set.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With