A caveat for subparsers

Argparse provides subparsers. They let you easily handle subcommands. What is a subcommand? A command that is specified as an argument for a command. A typical example is Git, where you have subcommands like git status, git commit and so on.

One common and very convenient way to implement subcommands is to create a function and link this to the subcommand with a line like this:

subparser.set_defaults(func=_import)

When the subcommand is given, the function is called.

There is one caveat, though. This magic is explicitly invoked by a line like

args.func(args)

This line must be the last thing you do when handling your args. Else global options do not work because code that uses them is never called. An example is logging, which is typically a global option. That is, logging is specified before the subcommand and affects all subcommands, like this:

footool --log mylog.log import

This option is typically handled by a line like the following one:

if not args.logfile:
    logfilename = os.path.splitext(os.path.basename(__file__))[0] + '.log'
else:
    logfilename = args.logfile

So, when you specify a logfile name, this is used. If not, the app chooses the name by itself, based on the apps name.

When you call args.func(args) before these lines, the subcommands are handled by the subparsers and these lines are never reached because the subparsers just call the function that you have specified (_import in our case). So, best call args.func(args) after you’re done with option processing.

links

social