Python environment configuration simplified.
Config2 (for Python) - which is highly inspired by node-config - organizes hierarchical configurations for your app deployments.
It lets you define a set of default parameters, and extend them for different deployment environments (development, qa, staging, production, etc.).
Configurations are stored in configuration files within your application, and can be overridden and extended by environment variables, command line parameters, or external sources.
This gives your application a consistent configuration interface shared among a growing list of npm modules also using node-config.
NOTE: This project is more or less in pair with node-config implementation, with exception for some fluff that could be considered too much magic such as deployment specific multi-instance deployments which I so far haven't found any good motivation for, and some other questionable advanced features mentioned in the wiki pages.
...based on node-config project guidelines:
- Simple - Get started fast
Powerful - For multi-node enterprise deployment- excluded because with power comes responsability- Flexible - Supporting multiple config file formats
- Lightweight - Small file and memory footprint
- Predictable - Well tested foundation for module and app developers
Install using pip:
$ pip install config21. Assuming we have a python application project...
some_project
└── app.py
app.py - some app making serious $$$
# business logic
print('$$$')2. Let's add some environment specific config files...
some_project
└── config
├── default.yml
├── development.yml
├── foo.yml
└── production.yml
└── app.py
default.yml - with some bogus nested settings shared for all environments (defaults)
a1: DEFAULT 1
a2:
b1: [1, 2, 3]
b2:
- foo
- bar
b3:
c1: 1
c2: "DEFAULT 2"development.yml - with some bogus nested settings overriden for development environment (overriden)
a2:
b2:
- DEV 1
b3:
c2: "DEV 2"
some_key_only_for_dev: truefoo.yml - with some bogus nested settings overriden for foo environment (overriden)
a2:
b2:
- FOO 1
b3:
c2: "FOO 2"
some_key_only_for_foo: trueproduction.yml - with some bogus nested settings overriden for production environment (overriden)
a2:
b2:
- PROD 1
b3:
c2: "PROD 2"
some_key_only_for_prod: true3. Let's now run the app using various environments...
$ python app.py
from config2.config import config
config.get_env() # => None
config.get() # => {'a1': 'DEFAULT 1', 'a2': {'b1': [1, 2, 3], 'b2': ['foo', 'bar'], 'b3': {'c1': 1, 'c2': 'DEFAULT 2'}}}
config.a1 # => 'DEFAULT 1'
config.a2 # => {'b1': [1, 2, 3], 'b2': ['foo', 'bar'], 'b3': {'c1': 1, 'c2': 'DEFAULT 2'}}
config.a2.b3.c2 # => 'DEFAULT 2'
print('$$$')$ ENV=development python app.py
from config2.config import config
config.get_env() # => 'development'
config.get() # => {'a1': 'DEFAULT 1', 'a2': {'b1': [1, 2, 3], 'b2': ['DEV 1'], 'b3': {'c1': 1, 'c2': 'DEV 2'}}, 'some_key_only_for_dev': True}
config.a1 # => 'DEFAULT 1'
config.a2 # => {'b1': [1, 2, 3], 'b2': ['DEV 1'], 'b3': {'c1': 1, 'c2': 'DEV 2'}}
config.a2.b3.c2 # => 'DEV was here 2'
config.some_key_only_for_dev # => True
config.some_key_only_for_foo # => AttributeError
config.some_key_only_for_prod # => AttributeError
print('$$$')$ ENV=foo python app.py
from config2.config import config
config.get_env() # => 'foo'
config.get() # => {'a1': 'DEFAULT 1', 'a2': {'b1': [1, 2, 3], 'b2': ['FOO 1'], 'b3': {'c1': 1, 'c2': 'FOO 2'}}, 'some_key_only_for_foo': True}
config.a1 # => 'DEFAULT 1'
config.a2 # => {'b1': [1, 2, 3], 'b2': ['FOO 1'], 'b3': {'c1': 1, 'c2': 'FOO 2'}}
config.a2.b3.c2 # => 'FOO was here 2'
config.key_only_for_foo # => True
config.some_key_only_for_dev # => AttributeError
config.some_key_only_for_prod # => AttributeError
print('$$$')$ ENV=production python app.py
from config2.config import config
config.get_env() # => 'production'
config.get() # => {'a1': 'DEFAULT 1', 'a2': {'b1': [1, 2, 3], 'b2': ['PROD 1'], 'b3': {'c1': 1, 'c2': 'PROD 2'}}, 'some_key_only_for_foo': True}
config.a1 # => 'DEFAULT 1'
config.a2 # => {'b1': [1, 2, 3], 'b2': ['PROD 1'], 'b3': {'c1': 1, 'c2': 'PROD 2'}}
config.a2.b3.c2 # => 'PROD was here 2'
config.some_key_only_for_prod # => True
config.some_key_only_for_dev # => AttributeError
config.some_key_only_for_foo # => AttributeError
print('$$$')etc.
4. Optionally, let's now introduce custom config environment variables...
some_project
└── config
├── custom-environment-variables.yml
├── default.yml
├── development.yml
├── foo.yml
└── production.yml
└── app.py
custom-environment-variables.yml - with mappings of config keys to environment variables
a1: A1
a2:
b3:
c2: C25. Let's now run the app using custom environment variables to override config...
$ A1=x C2=y python app.py
from config2.config import config
config.get_env() # => None
config.get() # => {'a1': 'x', 'a2': {'b1': [1, 2, 3], 'b2': ['foo', 'bar'], 'b3': {'c1': 1, 'c2': 'y'}}}
config.a1 # => 'x'
config.a2 # => {'b1': [1, 2, 3], 'b2': ['foo', 'bar'], 'b3': {'c1': 1, 'c2': 'y'}}
config.a2.b3.c2 # => 'y'
print('$$$')Clone down source code:
$ make installRun colorful tests, with only native environment (dependency sandboxing up to you):
$ make testRun less colorful tests, with multi-environment (using tox):
$ make test-toxThis project was mainly initiated - in lack of existing alternatives - to be used at our work at Markable.ai to have common code conventions between various programming environments where Python (research, CV, AI) and Node.js (I/O, APIs, UIs, scripts) currently are most used.
Released under the MIT license.