Thinking about the best way to handle command registration
Suppose that you have a Python utility program that does a number of
related things; it's invoked as '
program command ....', and decides
what to do based on what the command is. The obvious way to implement
this in Python is to have a function for each command and a top-level
dispatcher that looks up the function to call for each command and
passes it the arguments to process. Clearly you don't want to hard-code
this in the dispatcher function in a big
elif block; instead
you want to somehow register all the commands in a simpler, easier to
Since I have been writing such a utility program, I have found myself wondering what the best way of doing this is (where 'best' means 'most natural, obvious, and easy to follow'). So far I've come up with a number of possible ways:
- have a dictionary where the key is the command name and the value
is a tuple of information about the command (including the function
to call, the minimum and maximum number of command line arguments
it takes, and some help text).
(The obvious and simple approach, but it starts getting more and more awkward as you add more per-command data to keep track of. You can use a structure instead of a tuple, but then you are complicating the simple scheme.)
- call a registration function to define a command, giving it all
of the details:
def cmdfunc(args, ...):
register('cmd', cmdfunc, ...)
(The registration function can have defaults for various things.)
- use a decorator function to do the registration:
def cmdfunc(args, ...):
- attach all of the information to the function as function attributes, and have a simple scheme to relate the command to the function name. The top level dispatcher then uses introspection to find if the command exists and to pull out anything else it needs.
Naturally you can combine aspects of all of these together to create hybrid systems (for example, using the function's docstring for some of the user help text).
Of these, I suspect that the decorator function approach is the most Pythonic but is also the second hardest for people who are not experienced Python programmers to follow (introspection would probably be the hardest). Since that last issue is a consideration, I am leaning towards using the plain registration function approach.
(My current code mostly uses the simple dictionary approach, but it's not the clearest thing to follow.)