Wandering Thoughts archives

2020-08-22

Some bits on making Python's argparse module work like Unix usually does

I recently discovered that argparse allows you to abbreviate long options, and then Chris Wellons wrote about Conventions for (Unix) Command Line Options, which included a criticism of argparse. I'm not going to write about how to make argparse behave today, because I haven't explored that in full; instead, this is some quick notes from the documentation and my past experiences.

First, both Wellons and I had a bad reaction to argparse accepting abbreviated options. However, based on the documentation you probably have to accept it, because of an important postscript note:

Changed in version 3.8: In previous versions, allow_abbrev [being False] also disabled grouping of short flags such as -vv to mean -v -v.

Almost no one has Python 3.8, which means that the cure here is worse than the disease. Not accepting grouped short flags is much worse than accepting abbreviated long flags, so until Python 3.8+ is pervasive we're stuck with the latter.

As it implicitly documents (in the form of its example), argparse allows the non-traditional style of options being intermixed with non-option arguments on the command line, instead of requiring all options to be before non-options. There is no way to control this. Argparse does accept '--' to terminate the option list (with some caveats), after which things that look like options are non-option arguments.

In general, using the nargs argument for add_argument() is neither necessary nor useful for options (and has issues when used with non-options). Setting things like 'type=str' or 'action="append" causes the argument parser to do the right thing; similarly, it does the right thing when the action doesn't consume any argument value (this behavior is documented in a postscript of the nargs section). As Wellons noted, argparse can fall down badly if you attempt to create an option that takes an optional value. Fortunately, I don't think you should do that and should stick to options either always taking a value or never doing so. Argparse's own examples use 'nargs="?"' for non-options arguments that are in fact optional.

Argparse makes a weird attempt to handle command line arguments that are negative numbers, as documented in Arguments containing -. This isn't how traditional Unix commands behave with such arguments, where a leading '-' is a leading '-' no matter what, with no attempts to guess at what should happen. This behavior is not currently optional and I don't think there's a really good way to trick argparse into not doing it.

(Actually reading much of the argparse documentation has already taught me useful things I didn't know, such as how the dest argument is optional. I'm not sure I'd want to ever leave it out, though; explicit is better than implicit, and using 'dest' leaves a visible reminder in the code of what attribute holds the result.)

python/ArgparseSomeUnixNotes written at 23:59:39; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.