Configuration Files

When configuration file support is enabled (by specifying config_option in docoptcfg), Python’s native configparser module is used to read configuration files. That means only INI/INF-type config files are supported.

An example configuration file is:

[my_script]
log-file = file_config.log
runtime = 10
threads = 11

Below are a few things to keep in mind.

The Basics

Let’s get some basics out of the way. When calling docoptcfg() with the config_option argument, the value of that argument should be one of the options defined in your docstring. For example if we’ve got this docstring:

My little script.

Usage:
    my_script [options]

Options:
    -c FILE --config=FILE       Path to INI config file.
    -l FILE --log-file=FILE     Write to this log file.
    -r NUM --runtime=NUM        How long before exiting.
    -t NUM --threads=NUM        Number of threads.

Then config_option should be set to one of those, such as config_option='--config'. You’ll need the hyphens.

Another thing to point out is that docoptcfg ignores re-defining configuration files within configuration files. So if your end user has this:

[my_script]
config = new_config.ini
runtime = 10

Then docoptcfg will just ignore the config setting. It will read the rest of the config file like normal.

Lastly, you can combine configuration files and environment variables. So your users can define a configuration file with PREFIX_CONFIG=/path/to/config.ini instead of through the command line.

Exception Handling

Unlike environment variables which don’t throw any exceptions, configuration file handling may raise two exceptions:

  • docoptcfg.DocoptcfgError
  • docoptcfg.DocoptcfgFileError

DocoptcfgError

This one’s easy. It’s only raised under one scenario: when you (the developer) specifies the wrong option for config_option when calling docoptcfg(). With the above example docstring, if you do docoptcfg(__doc__, config_option='--i-dont-exist') then DocoptcfgError will be raised.

DocoptcfgFileError

This one may be raised by a mistake on your end-users’ part. Be sure to handle this. This is raised on any error that may come up while attempting to read and parse a config file. Situations include:

  • File not found
  • Permissions
  • Corrupt/binary data instead of text data
  • Malformed section formatting
  • Missing section
  • Non-boolean value for boolean options (valid values are listed in the configparser documentation)

A simple way to handle this is:

try:
    CONFIG = docoptcfg(__doc__, config_option='--config')
except DocoptcfgFileError as exc:
    log.error('Failed reading: %s', str(exc))
    CONFIG = docoptcfg(__doc__)

Section Name

docoptcfg will only focus on one section in the config file. The name of that section must match the name of your program specified in your docstring. The example above has the section named “my_script”. Therefore in your docstring the first word after “Usage:” should match.

Short Names

Like environment variables, only long option names are used. In the example above we’ve got -l FILE --log-file=FILE but docoptcfg will only look for log-file.

Flags/Booleans

Flags in config files must be yes, no, on, off, true, false, 1, or 0. More info in the configparser documentation.

Repeating Options

Docopt supports repeating options by specifying an ellipses in the docstring. An example:

Test handling of ... options.

Usage:
    my_script [--config=FILE] [--flag]... [--key=VAL]...

Options:
    --config=FILE   Path INI config file.
    --flag          Boolean value.
    --key=VAL       Key value value.

In this case, docopt gives you integers for flags (instead of booleans) and lists for key/value options (instead of strings).

docoptcfg supports this in configuration files as well:

  1. Configuration file options for flags are expected to be integers.
  2. Configuration file options for key/values can be delimited by newlines.

Here’s a quick example:

[my_script]
key =
    a
    b
    c
flag = 2

The above is the equivalent of my_script --key=a --key=b --key=c --flag --flag.