Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is possible to use decorator to monkey patch the global variables?

Is possible to monkey patch the global variables?

For my case, I setup the a global variable to be the default logger of whole file, but for some special function I would use a decorator to change the logger and add some extra information.

Such as follow code:

libmonkey.py

logger = logging.getLogger(__name__)

@change_logger('import')
def do_some():
    logger.debug('This is a debug')
    #do some things

def do_some2():
    logger.debug('This is a debug')
    #do some things

decorator.py

def change_logger(name):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*arg, **kwargs):
            logger = logging.getLogger(name)
            func(*arg, **kwargs)
        return wrapper
    return decorator

And when I do follow code, the log of do_some() is not go to logger import instead of libmonkey

from libmonkey import do_some, do_some2

#skip code for set logging lvl to debug, and output logging to stream.
do_some()
do_some2()

So how to use decorator to monkey patching the global variable.

like image 386
tywtyw2002 Avatar asked Oct 19 '25 01:10

tywtyw2002


1 Answers

You can alter the function globals temporarily:

_sentinel = object()

def change_logger(name):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*arg, **kwargs):
            old_logger = func.__globals__.get('logger', _sentinel)
            func.__globals__['logger'] = logging.getLogger(name)
            try:
                result = func(*arg, **kwargs)
            finally:
                if old_logger is not _sentinel:
                    func.__globals__['logger'] = old_logger
                else:
                    del func.__globals__['logger']
            return result
        return wrapper
    return decorator

This is not thread safe; you are altering the globals not just for this function but for the whole module.

like image 179
Martijn Pieters Avatar answered Oct 21 '25 15:10

Martijn Pieters



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!