|
| 1 | +""" |
| 2 | +Poor Man's Configurator. Probably a terrible idea. Example usage: |
| 3 | +$ python train.py config/override_file.py --batch_size=32 |
| 4 | +this will first run config/override_file.py, then override batch_size to 32 |
| 5 | +
|
| 6 | +The code in this file will be run as follows from e.g. train.py: |
| 7 | +>>> exec(open('configurator.py').read()) |
| 8 | +
|
| 9 | +So it's not a Python module, it's just shuttling this code away from train.py |
| 10 | +The code in this script then overrides the globals() |
| 11 | +
|
| 12 | +I know people are not going to love this, I just really dislike configuration |
| 13 | +complexity and having to prepend config. to every single variable. If someone |
| 14 | +comes up with a better simple Python solution I am all ears. |
| 15 | +""" |
| 16 | + |
| 17 | +import sys |
| 18 | +from ast import literal_eval |
| 19 | + |
| 20 | +for arg in sys.argv[1:]: |
| 21 | + if '=' not in arg: |
| 22 | + # assume it's the name of a config file |
| 23 | + assert not arg.startswith('--') |
| 24 | + config_file = arg |
| 25 | + print(f"Overriding config with {config_file}:") |
| 26 | + with open(config_file) as f: |
| 27 | + print(f.read()) |
| 28 | + exec(open(config_file).read()) |
| 29 | + else: |
| 30 | + # assume it's a --key=value argument |
| 31 | + assert arg.startswith('--') |
| 32 | + key, val = arg.split('=') |
| 33 | + key = key[2:] |
| 34 | + if key in globals(): |
| 35 | + try: |
| 36 | + # attempt to eval it it (e.g. if bool, number, or etc) |
| 37 | + attempt = literal_eval(val) |
| 38 | + except (SyntaxError, ValueError): |
| 39 | + # if that goes wrong, just use the string |
| 40 | + attempt = val |
| 41 | + # ensure the types match ok |
| 42 | + assert type(attempt) == type(globals()[key]) |
| 43 | + # cross fingers |
| 44 | + print(f"Overriding: {key} = {attempt}") |
| 45 | + globals()[key] = attempt |
| 46 | + else: |
| 47 | + raise ValueError(f"Unknown config key: {key}") |
0 commit comments