Rationale¶

Configuration management in terms of simply parsing a config file and
getting or setting keys is a solved problem. Depending on application
requirements, one can use stdlib provided packages like
configparser
and json
, third party packages providing
support for formats like YAML and TOML, or simply use Python itself as
a means of dynamic configuration, as popular Python web frameworks do.
For extremely simple applications and prototypes, using the filesystem and a popular data serialization format as the only means of configuration is a perfectly reasonable solution. But what about production? Multiple application environments? That’s a solved problem, too — just follow the twelve-factor app and use the environment as configuration!
But now you have to do a lot of work for configuration keys that aren’t simple strings. Data validation, coercion, normalization, graceful fallbacks — if you’re motivated enough to concern yourself with such things, of course. Be honest, how many times have you seen (or written) some variation of this?
SECRET_KEY = os.getenv('SECRET_KEY')
if not SECRET_KEY:
SECRET_KEY = generate_secret_key()
RDBMS_PORT = int(os.getenv('RDBMS_PORT', 5432))
And what about secrets? Assuming you’re fortunate enough to be able to utilize a secrets management solution like HashiCorp Vault or AWS SSM Parameter Store, you are more or less on your own to integrate them with your application, using a third-party library or a shim. Or maybe you don’t use a secrets management tool, and opt for the “simpler” solution consisting of reading a file not checked into source control.

Is a multi-tiered, encoding agnostic, schema driven configuration parsing kitchen sink really necessary for most applications? No. Should you have ten different configuration sources? Probably not. But if you find yourself writing a similar solution repetitively and wishing there was a better way, try out pitstop.