Globally scoped configuration with argparse integration
Project description
Effortless Config
Globally scoped configuration with argparse integration.
Installation
pip install effortless-config
Rationale
- When building machine learning models, I often find myself with a file named
config.py
that has a bunch of global variables that I reference throughout the codebase. - As the work progresses, I end up with groups of specific configuration settings that correspond to specific experiments.
- I want to be able to select configuration group on the command line when I start an experiment.
- And I want to be able to override certain settings within that experiment, from the command line.
Usage
Defining configuration
Inside some file in your project, for example example/config.py
:
from effortless_config import Config, setting
class config(Config): # notice lowercase c
groups = ['experiment1', 'experiment2']
SOME_INTEGER_SETTING = setting(10, experiment1=20, experiment2=30)
FLOAT_SETTING = setting(0.5)
A_BOOLEAN = setting(False, experiment1=True)
MY_STRING_SETTING = setting('foo', experiment2='bar')
SOME_OTHER_INTEGER = 100
First we create a class that extends effortless_config.Config
. Inside it we add configurable parameters with the effortless_config.setting
method. setting
has the signature:
def setting(default: SettingType, **kwargs: SettingType):
"""
Create a new configurable parameter, inside a class that extends Config.
Args:
default: Default parameter value.
**kwargs: Map of group name to group value.
Returns:
A new setting.
"""
(...where SettingType
is Union[int, float, str, bool]
.)
In this example, FLOAT_SETTING
has no groups defined, so this setting will use the default value for all groups. It can still be overridden on the command line though. But SOME_OTHER_INTEGER
will always be fixed, since it's not wrapped in setting
.
Using the configuration
Then in your code you can use these settings, for example inexample/main.py
:
from .config import config
if __name__ == '__main__':
config.parse_args()
print(f'SOME_INTEGER_SETTING is {config.SOME_INTEGER_SETTING}')
print(f'FLOAT_SETTING is {config.FLOAT_SETTING}')
print(f'A_BOOLEAN is {config.A_BOOLEAN}')
print(f'MY_STRING_SETTING is {config.MY_STRING_SETTING}')
print(f'SOME_OTHER_INTEGER is {config.SOME_OTHER_INTEGER}')
When we invoke main.py without any arguments, we get the default settings:
$ python -m example.main
SOME_INTEGER_SETTING is 10
FLOAT_SETTING is 0.5
A_BOOLEAN is False
MY_STRING_SETTING is foo
SOME_OTHER_INTEGER is 100
When we pass an configuration group using the --configuration
parameter, we get different values:
$ python -m example.main --configuration experiment1
SOME_INTEGER_SETTING is 20
FLOAT_SETTING is 0.5
A_BOOLEAN is True
MY_STRING_SETTING is foo
SOME_OTHER_INTEGER is 100
We can also override individual settings:
$ python -m example.main --some-integer-setting 40 --float-setting -5
SOME_INTEGER_SETTING is 40
FLOAT_SETTING is -5.0
A_BOOLEAN is False
MY_STRING_SETTING is foo
SOME_OTHER_INTEGER is 100
As well as combining groups with individual settings:
$ python -m example.main --configuration experiment1 --some-integer-setting 40
SOME_INTEGER_SETTING is 40
FLOAT_SETTING is 0.5
A_BOOLEAN is True
MY_STRING_SETTING is foo
SOME_OTHER_INTEGER is 100
You can see all available settings using the -h
flag:
$ python -m example.main -h
usage: main.py [-h] [--configuration {experiment1,experiment2}]
[--some-integer-setting SOME_INTEGER_SETTING]
[--float-setting FLOAT_SETTING] [--a-boolean {true,false}]
[--my-string-setting MY_STRING_SETTING]
optional arguments:
-h, --help show this help message and exit
--configuration {experiment1,experiment2}, -c {experiment1,experiment2}
--some-integer-setting SOME_INTEGER_SETTING
--float-setting FLOAT_SETTING
--a-boolean {true,false}
--my-string-setting MY_STRING_SETTING
Testing
When writing tests, you can use the config.override
context manager to override individual settings:
import pytest
from .config import config
def test_with_context_manager():
with config.override(FLOAT_SETTING=0.8, A_BOOLEAN=True):
assert config.FLOAT_SETTING * config.SOME_INTEGER_SETTING == 8
assert config.A_BOOLEAN is True
The config.override
method can also be used without context management in conjunction with config.reset_to_defaults
:
def test_with_manual_reset():
config.override(FLOAT_SETTING=0.8, A_BOOLEAN=True)
assert config.FLOAT_SETTING * config.SOME_INTEGER_SETTING == 8
assert config.A_BOOLEAN is True
config.reset_to_defaults()
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for effortless_config-0.1.4-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 63607cd18007ff8860b439c8d541d6a8d7df9604f7623f9b5e5b85a985bf16f5 |
|
MD5 | fa7fe10b610c87e710142e292a6a07a1 |
|
BLAKE2b-256 | bb614e8d6ece6109a99399d2c821ec7feb8f2f9345a54268ccb2cfae517cbf99 |