How can I reload a python class if file is changed on disk?

1k Views Asked by At

To support runtime changes of parameters stored in source class file and used as an object with fields, how can I check if the source file for the object was modified since runtime started or since the last time it was reloaded, and reload the class and make a new instance of the object?

2

There are 2 best solutions below

0
tobi delbruck On

This method seems to work:

def reload_class_if_modified(obj:object, every:int=1)->object:
    """
    Reloads an object if the source file was modified since runtime started or since last reloaded

    :param obj: the original object
    :param every: only check every this many times we are invoked

    :returns: the original object if classpath file has not been modified 
              since startup or last reload time, otherwise the reloaded object
    """
    reload_class_if_modified.counter+=1
    if reload_class_if_modified.counter>1 and reload_class_if_modified.counter%every!=0:
        return obj
    try:
        module=inspect.getmodule(obj)
        cp=Path(module.__file__)
        mtime=cp.stat().st_mtime
        classname=type(obj).__name__

        if (mtime>reload_class_if_modified.start_time and (not (classname in reload_class_if_modified.dict))) \
                or ((classname in reload_class_if_modified.dict) and mtime>reload_class_if_modified.dict[classname]):
            importlib.reload(module)
            class_ =getattr(module,classname)
            o=class_()
            reload_class_if_modified.dict[classname]=mtime
            return o
        else:
            return obj
    except Exception as e:
        logger.error(f'could not reload {obj}: got exception {e}')
        return obj

reload_class_if_modified.dict=dict()
reload_class_if_modified.start_time=time()
reload_class_if_modified.counter=0

Use it like this:

import neural_mpc_settings
from time import sleep as sleep
g=neural_mpc_settings()
while True:
    g=reload_class_if_modified(g, every=10)
    print(g.MIN_SPEED_MPS, end='\r')
    sleep(.1)

where neural_mpc_settings is

class neural_mpc_settings():
    MIN_SPEED_MPS = 5.0

When I change neural_mpc_settings.py on disk, the class is reloaded and the new object returned reflects the new class fields.

0
metaperture On

You might want to consider using a library like watchdog, which would let you trigger a handler whenever the file is changed. Instead of collocating your parameters with the code, you could stored them in a data file, with a data loader method that was called on startup and whenever the underlying data file was changed.