python - 是否可以使用装饰器来猴子修补全局变量?

标签 python monkeypatching

是否可以对全局变量进行猴子修补?

对于我的情况,我将全局变量设置为整个文件的默认记录器,但对于某些特殊功能,我会使用装饰器来更改记录器并添加一些额外信息。

如以下代码:

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

装饰器.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() 的日志不会转到记录器 import 而不是 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

不是线程安全的;您不仅要为此功能而且要为整个模块更改全局变量。

关于python - 是否可以使用装饰器来猴子修补全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30901949/

相关文章:

python - mock.patch() 不修补在函数调用中调用了几个级别的类

rust - 如何对ncurses crate 进行monkeypatch(模拟)调用?

ruby-on-rails - 带有遗留只读数据库的 Factory Girl

python - 猴子补丁 Python 类

python - 如何构造一个首先在两列之间执行算术运算并将其作为新列返回的 SQLAlchemy 查询?

python - 如何在 pandas 中将 '1:30:20' 字符串转换为时间格式

python - python的 "set"稳定吗?

python - 如何在python中分离混合词(波斯语和英语)

python - 为什么我的排序代码执行时间不一致?

assembly - PC寄存器上的ARM LDR指令