diff --git a/ilurl/utils/context_managers.py b/ilurl/utils/context_managers.py index a023d0b..4fd04b3 100644 --- a/ilurl/utils/context_managers.py +++ b/ilurl/utils/context_managers.py @@ -3,7 +3,7 @@ class PipeGuard(object): - """PipeGuards supresses stdout in order to prevent text outputs to interfere + """PipeGuard supresses stdout in order to prevent text outputs """ def __enter__(self): self._stdout = sys.stdout @@ -12,4 +12,3 @@ def __enter__(self): def __exit__(self, *args, **kwargs): sys.stdout.close() sys.stdout = self._stdout - diff --git a/ilurl/utils/decorators.py b/ilurl/utils/decorators.py index 903af29..e355473 100644 --- a/ilurl/utils/decorators.py +++ b/ilurl/utils/decorators.py @@ -1,9 +1,60 @@ -import time +import pdb +from pathlib import Path +from time import time +import json import sys +import multiprocessing as mp from ilurl.utils.context_managers import PipeGuard +def chronological(fnc): + """Times execution of fnc, storing on folder if path exists + + Parameters: + ---------- + * fnc: function + An anonymous function decorated by the user + + Returns: + ------- + * fnc: function + An anonymous function that will be timed + """ + _data = {} + def f(*args, **kwargs): + _data['start'] = time() + res = fnc(*args, **kwargs) + _data['finish'] = time() + _data['elapsed'] = _data['finish'] - _data['start'] + + # if res is a valid sys path + if Path(str(res)).exists(): + target_path = Path(str(res)) / 'time.json' + with target_path.open('w') as f: + json.dump(_data, f) + else: + print(f'''\tChronological: + --------------- + \t start:{_data['start']} + \t finish:{_data['finish']} + \t elapsed:{_data['elapsed']}\n\n''') + return res + return f + + def processable(fnc): + """Supresses stdout during fnc execution writing output only + + Parameters: + ---------- + * fnc: function + An anonymous function decorated by the user + + Returns: + ------- + * fnc: function + An anonymous function that will have stdout supressed + """ def f(*args, **kwargs): with PipeGuard(): res = fnc(*args, **kwargs) @@ -13,6 +64,8 @@ def f(*args, **kwargs): return f +# TODO: not working -- lock has to be shared? +# implemented with a global lock on jobs/train.py def delayable(lock): """delayable receives a lock and delays fnc execution @@ -41,11 +94,11 @@ def delay(fnc): calling """ def f(*args, **kwargs): - lock.acquire() + LOCK.acquire() try: time.sleep(1) finally: - lock.release() + LOCK.release() return fnc(*args, **kwargs) return fnc return delay diff --git a/jobs/train.py b/jobs/train.py index a5e82c1..0036b71 100644 --- a/jobs/train.py +++ b/jobs/train.py @@ -9,7 +9,7 @@ import time from models.train import main as train -from ilurl.utils.decorators import processable, delayable +from ilurl.utils.decorators import processable ILURL_HOME = os.environ['ILURL_HOME'] @@ -18,8 +18,25 @@ LOCK = mp.Lock() -@delayable(LOCK) def delay_train(*args, **kwargs): + """delays execution by 1 sec. + + Parameters: + ----------- + * fnc: function + An anonymous function decorated by the user + + Returns: + ------- + * fnc : function + An anonymous function to be executed 1 sec. after + calling + """ + LOCK.acquire() + try: + time.sleep(1) + finally: + LOCK.release() return train(*args, **kwargs) @@ -85,7 +102,7 @@ def train_batch(): else: rvs = [] for cfg in train_configs: - rvs.append(main(cfg)) + rvs.append(delay_train([cfg])) # Create a directory and move newly created files paths = [Path(f) for f in rvs] commons = [p.parent for p in paths] @@ -110,6 +127,6 @@ def train_job(): if __name__ == '__main__': # enable this in order to have a nice textual ouput - # train_batch() - train_job() + train_batch() + # train_job()