The options problem in Python

September 17, 2012

Suppose that you have a Python program that takes command line arguments, including switches (a 'verbose' switch is common, for example). These options change the program's behavior and logic in relatively low-level places, possibly pervasively (again a 'verbose' switch is a good example, as is a 'dryrun' switch).

So, how do you pass information about these command-line arguments down to low-level code? I can think of at least four, most of which I've used in my code from time time, and I have no idea which is considered the best and most Pythonic. The four that come to mind are:

  • global variables for each option or setting. This involves a profusion of global variables, which doesn't make me happy.

  • a single global 'options' object, which holds all of the options and settings (probably in expanded form).

  • passing individual variables for each option down the call chain to routines that need them. The problem with this is that you wind up with large argument lists that are passed to a lot of high level functions purely so that the functions can pass them along to low level routes as needed.

  • passing a single 'options' object down the call chain to routines that need any option. This at least adds fewer parameters to calls, but you pretty soon wind up in a situation where your options object is effectively a global variable that's being passed as part of the function arguments.

(Let's assume for the moment that you can't restructure your program in any natural way to localize knowledge about a particular option in a single small place; you really do have pervasive options.)

I don't really like any of these, although in some situations some of them are less annoying than others. Since I continue to not like global variables, right now I usually do some variant of the third or the fourth without any real enthusiasm for it.

I feel like there should be a better way, if only I was clever enough to see it.

(All of this is on my mind right now because I'm confronting one of my old programs with what is now bad argument handling and thinking about overhauling all of it.)

Comments on this page:

From at 2012-09-17 05:49:13:

I would prefer to wrap these options into a standalone module in this situation. The interface for accessing options could be designed as functions , global variables or classes in this module. Python module provides a namespace.

From at 2012-09-17 06:36:00:

I second the comment above, but only because I've seen it done (actually in Ruby, but it's not that different). Effectively a singleton class or just a module with class methods providing accessors to the options.

But since you need to import that module into the top namespace it is actually just a fancy way of doing your option #2, wrapped up in a pretty package.

From at 2012-09-17 08:35:50:

What do you think about argparse in python >= 2.7?

From at 2012-09-17 12:50:58:

For myself, I've found that options handling for most of my projects works well as:

First thing in the program (in main() or a similarly scoped method), parse the arguments into an "options" object. Obviously this has to happen before any program logic executes, so you know what all the options are before actually doing anything.

Pass the object to a new instance of the primary class for the program and store it as an instance variable on that object. This makes all the options available to the "controller" of the application (which probably needs access all of them at some point).

Most supporting classes and functions only need one or two of the options, so they are just passed in as parameters. (If another object needed more options, I would probably pass the full object in, but I find that this is fairly rare.)

In a few cases, I've separated the options object into sub-objects (by some grouping of options that are logically related) and passed those around to the helper objects, but I don't find that I need this approach too often.

Written on 17 September 2012.
« The problem with noise
My Python versions »

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

Last modified: Mon Sep 17 03:03:27 2012
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.