Skip to content

Instantly share code, notes, and snippets.

@wrongu
Created November 25, 2022 22:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wrongu/52ad0fbcda040f658dff3f604e609692 to your computer and use it in GitHub Desktop.
Save wrongu/52ad0fbcda040f658dff3f604e609692 to your computer and use it in GitHub Desktop.
Argparse action-handler trick to add new command line arguments at parsing time depending on value of some other argument
import argparse
from typing import Dict
class ActionHandler(argparse.Action):
def __init__(self, *args, **kwargs):
super(ActionHandler, self).__init__(*args, **kwargs)
# ran_once is used to flag if __call__ has been run yet. This avoids an infinite loop.
self.ran_once = False
def __call__(self, parser, args, values, option_string=None):
if not self.ran_once:
self.ran_once = True
if values == "alpha":
# Add an extra option called '--bar'
parser.add_argument("--bar", default=1, type=int)
elif values == "bravo":
# Add an extra option called '--baz'
parser.add_argument("--baz", default=2.0, type=float)
# Recursive parse, storing results in the same 'args' Namespace object so it's transparent to the caller.
parser.parse_known_args(namespace=args)
def my_parse_args(parser):
# Pre-parse onece to populate any extra subparser stuff. Using 'parse_known_args' is permissive
# and doesn't raise any errors for unrecognized values.
parser.parse_known_args()
# Parse for real!
return parser.parse_args()
parser = argparse.ArgumentParser()
parser.add_argument("--foo", default="alpha", choices=["alpha", "bravo"], action=ActionHandler)
args = my_parse_args(parser)
print(args)
# Test cases to try out
# $ python3 -m conditional_argparse # should see (foo=alpha, bar=1)
# $ python3 -m conditional_argparse --foo alpha --bar 2 # should see (foo=alpha, bar=2)
# $ python3 -m conditional_argparse --foo alpha --baz 5.0 # Error! baz is only defined if foo=bravo
# $ python3 -m conditional_argparse --foo bravo --baz 5.0 # should see (foo=alpha, baz=5.0)
# $ python3 -m conditional_argparse --foo bravo --bar 2 # Error! bar is only defined if foo=alpha
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment