Search code examples
pythonpython-3.x

Generic logging function wrapper


So what I'm trying to do is essentially take a bunch of pre-existing functions from commonly used libraries (such as subprocess,shutil,etc...) and wrap them in a function that will ouput what the function is doing as well as errors if any occur. My current code looks something like this.

def copytree(self,*args, **kwargs):
    self.debug(f":- Copying tree from \"{args[0]}\" to \"{args[1]}\"")
    try:
        shutil.copytree(*args,**kwargs)
    except Exception as e:
        self.error(f":- Failed to copy tree from \"{args[0]}\" to \"{args[1]}\" ; \"{e}\"")
        return False        
    self.debug(f":- Done")
    return True

I feel like there is probably a better way to do this in which there is a generic wrapper that can be used on any function but I am having trouble conceptualizing it. I'm also not sure if there is a way to account for functions that don't raise exceptions within said generic wrapper.

Also: self.debug and self.error are both just from the logging module


Solution

  • I would use function decorator and logging module.

    Here is a simple and dirty example :

    import logging
    logging.basicConfig(level=logging.INFO)
    
    
    # decorator
    def logged(func):
        def wrapper(*args, **kwargs):
            try:
                logging.info("started '{0}', parameters : {1} and {2}".
                             format(func.__name__, args, kwargs))
                return func(*args, **kwargs)
            except Exception as e:
                logging.exception(e)
        return wrapper
    
    
    @logged
    def foo(val):
        print(val/2)
    
    
    if __name__ == "__main__":
        foo("a")
    

    Output :

    INFO:root:started 'foo', parameters : ('a',) and {}

    ERROR:root:unsupported operand type(s) for /: 'str' and 'int'

    Traceback (most recent call last): File "C:/Users/xxxx.py", line 9, in wrapper return func(*args, **kwargs) File "C:/Users/xxxx.py", line 17, in foo print(val/2)

    TypeError: unsupported operand type(s) for /: 'str' and 'int'