/ configurator.py
configurator.py
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}")