Skip to content

07 - Mastering argparse

argparse introduction

  • The string module has the variables: ascii_letters, digits, punctuation that are list of what they describe. This is quite handy.
  • argparse.add_argument("-?", action=help)
  • argparse.add_argument("-v", action=version)
  • The action=count stores the number of times the flag was written. E.g. -sss would store 3.
  • action=extend is available starting from python3.8. It contrasts with append.
  • nargs values
  • * Zero or more
  • ? Zero or one
    • One or more
  • An integer telling how many parameters to consume
  • The choices parameter. The parameter can only take values present in a list.
  • The required=True tells the parser that an optional parameter is actually mandatory. Best word here would be a keyword flag.

Mutually exclusive arguments

# starwars.py
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)

group.add_argument('--light', action="store_true")
group.add_argument('--dark', action="store_true")

Allow abbreviation

By default, optional parameters are allowed to be passed in abbreviated form. That means any substring that matches the start of optional flag and it does not collides with any other start substring of other parameter. In the example above, all the below would work.

python starwars.py --light
python starwars.py --li
python starwars.py --l

You can disable this feature with the argument allow_abbrev=False in the ArgumentParser constructor.

Read positional arguments from file

# add_person.py

parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
parser.add_argument("name")
parser.add_argument("age")
add_person.py @daniel.txt

# daniel.txt
Daniel
32

Type

When you specify the type of the argument, the input will be passed to the call of what you specified in the type argument.

parse.add_argument("age", type=int) # Calls int(<whatever use typed>)

You can pass any callable.

parse.add_argument("character_code", type=ord)
parse.add_argument("file", type=open) # Not recommended
parse.add_argument("path", type=pathlib.Path)

Custom actions

# yoda.py
# The boolean optional action
parse.add_argument("--try", dest="Try", action=argparse.BooleanOptionalAction)
python yoda.py --try
python yoda.py --no-try
class BorkAction(argparse.Action):
    def __init__(self, option_strings, dest, nargs=None, **kwargs):
        if nargs is not None:
            raise ValueError("nargs is not allowed for this custom action")

    def __call__(self, parser, namespace, values, option_string=None):
        result = values + " Bork, bork, bork!"
        setattr(namespace, self.dest, result)

Alternatives to argparse

Exercise

  • Not something to do now, but it should be an interesting exercise to implement an argparse. I guess that also reading and understanding the code of argparse could be also interesting.
  • Read the document on the comparison between alternative parsers.