Today I learned that Python's argparse module allows you to abbreviate long command line options

July 14, 2020

Argparse is the standard Python library for Unix style command line argument handling; I use it in all of my Python programs these days. As part of this it supports the now standard long options, so you can have options like '--dead-disks' instead of just '-D' (there are only so many single characters to go around, and they can be hard to remember). Today I learned that argparse accepts abbreviations for these long options, provided that they're unambiguous. If you have a long option '--dead-disks' and no other long option that starts with 'd', argparse will accept all of '--dead-disk', '--dead', and even '--d' as meaning '--dead-disks'.

This is clearly documented in the argparse documentation if you bother to read it all (I never did), in Argument abbreviations (prefix matching). You can turn it off when constructing your ArgumentParser by setting the allow_abbrev keyword argument to 'false'. Unfortunately I don't think there's anything visible in a program's --help that will tell you whether or not it accepts abbreviated options; you have to either read the Python code or just try it with something harmless.

(It appears that optparse, argparse's predecessor, always allowed abbreviations, with no way to turn it off I'm basing this on a little mention of abbreviated long options in this section. This makes argparse a clear improvement here, since at least you can turn abbreviated options off if you want to.)

With my user hat on, I think this is a fine little feature. Long options are often, well, long, and if you can abbreviate them you might as well so people don't have to type as much (at least the people who don't have command line completion for options for your programs).

With my sysadmin hat on, I'm worried about the implications of abbreviated options accidentally getting embedded into other scripts, crontab entries, and so on. For instance, if the real option is '--dead-disks' but it's usually used with a single disk name, it would be easy to accidentally forget that it wasn't '--dead-disk' and embed that mistake in a script. Although this works today, it risks confusion in people who later read the script (including your future self). With heavily abbreviated options, evolving the program to add more options risks now making a previously unambiguous and working abbreviation now ambiguous and not working. If you add a new '--deadline' argument and scripts were using '--dead' as an abbreviation for '--dead-disks', suddenly they're going to start getting errors.

(You can think of this as a version of Postel's law, in which case The Harmful Consequences of the Robustness Principle sort of applies.)

Given this concern, it's tempting to update at least some of our sysadmin tools to disable abbreviated command line options and perhaps to make it my default argparse setting in future tools.


Comments on this page:

GNU getopt_long also does this, since forever.

I have made it a personal guideline to always use the long form and complete parameter name for any CLI I use in a shell script - there should be no excuse to use short options when you are anyways automating it out by using it in a script. Besides, it is often self-documenting.

By cks at 2020-07-16 22:10:40:

I wouldn't deliberately use a shortened version of an option in a script or crontab entry, so the risk I worry about is just forgetting what the real option is called. If I think I remember what the option is and it works, I'm unlikely to run the command with --help to carefully check that I'm not using an abbreviated form (especially if it's something like '--dead-disk' instead of '--dead-disks').

Written on 14 July 2020.
« Link: The Anatomy of a PromQL Query
A piece of phish spam with some clever URL obfuscation »

Page tools: View Source, View Normal, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Tue Jul 14 23:08:14 2020
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.