CFEconfig
This module exists to support the 12-factor App approach to configuration,
while also supporting convenient CLIs. This provides overlapping
functionality with the click
module, so you may not need this if you're
already using click, though by using both modules, you may benefit from our
distinct way of handling of config files and environment variables.
You can specify your configurable options in 3 ways, in any combination:
- Via environment variables named as 'PREFIX_OPTION_NAME' where prefix is a string you choose to identify the application instance.
- Via a YAML format configuration file of key-value pairs.
- Via arguments to your main script.
If the same option is specified in more than one place, CLI options take precendence over Config File options which take precendence over Environment Variables. This rule is the origin of the package name: CFE = CLI->File->Environment.
Further, and unlike click
, we push CLI and File-based options into the
Environment, so that applications and modules which do not use this module
can still read them. Code that does call config.get
, will receive immutable
values representing the state of the Environment variables at the time of
program start-up[1] , regardless of what has happened to environment
variables since.
We assume, but do not require, the use of the docopt
module to handle
configuration via command-line arguments. Any dict[str, str] of config values
will do, if you prefer to use alternate argument parsing.
Typical usage
- Read command-line args first, e.g.,
opts = docopt.docopt(__doc__)
- Read and store environment variables, with
config.load(opts, 'some_env_var_prefix')
. - Throughout the application, use
config.get()
to get a dict of configuration values orconfig.get('option_name')
to get a specific option value.
"""Usage: myapp.py [--foo] [--bar]"""
from cfeconfig import config
from docopt import docopt
from mylib import myfunction
opts = docopt(__doc__)
config.load(opts, 'myapp', 'config.yml') # Push opts to Environment.
CONFIG = config.get()
myfunction(CONFIG)
See DocTests in module functions for examples.
click
Theoretical Example usage with import os
from click import click
from cfeconfig import config
@click.command
@click.option('--a')
@click.option('--b')
def cli(**kwargs):
config.load(kwargs, 'myapp')
do_stuff() # More likely we're calling some code in our library.
def do_stuff():
CONFIG = config.get()
assert CONFIG['A'] == os.environ['MYAPP_A']
if __name__ == '__main__':
cli()
[1] More precisely, at the time config.load() was called.