Naming is hard, right?

Today I was extending an argparse based CLI application.

I wanted to add an optional argument so that I can pass in environment variables.

For this argparse has a special “action”, called append.

From the argparse documentation:

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='append')
>>> parser.parse_args('--foo 1 --foo 2'.split())
Namespace(foo=['1', '2'])

Awesome!

Now I can access all the provided values as foo.

Wait a moment

Wait! This does not match. I do not access foo but foos!

The problem is more visible when I use a real argument name.

I pass in several environment variables with --environment-variable each, and access them via environment_variable - this does not feel right.

Also it is not better to name the argument --environment-variables, as I pass in only one variable at a time.

Nobody likes a confusing cli API.

Colleague to the rescue

My colleague Colin pointed out that argparse’s add_argument method has a dest keyword, which determine the name under which the provided values are accessible.

Final solution

Combining append with dest is the way to go:

parser.add_argument('--foo', action='append', dest='foos')

and

parser.add_argument(
    '--environment-variable', action='append', dest='environment_variables'
)