其他分享
首页 > 其他分享> > 可能使用装饰器猴子修补全局变量吗?

可能使用装饰器猴子修补全局变量吗?

作者:互联网

猴子可以修补全局变量吗?

就我而言,我将全局变量设置为整个文件的默认记录器,但是对于某些特殊功能,我将使用装饰器来更改记录器并添加一些其他信息.

如以下代码:

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

当我遵循代码时,do_some()的日志不会转到logger导入,而不会转到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()

因此,如何使用装饰器来修补全局变量.

解决方法:

您可以临时更改函数全局变量:

_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

这不是线程安全的;您不仅要更改此函数的全局变量,还要更改整个模块的全局变量.

标签:monkeypatching,python
来源: https://codeday.me/bug/20191120/2041706.html