是否可以使用装饰器来猴子修补全局变量?
Is possible to use decorator to monkey patch the global variables?
是否可以对全局变量进行猴子修补?
对于我的情况,我将全局变量设置为整个文件的默认记录器,但对于某些特殊功能,我会使用装饰器来更改记录器并添加一些额外信息。
如以下代码:
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()
的日志不会转到记录器 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
这不是线程安全的;您不仅要为这个函数而且要为整个模块更改全局变量。
是否可以对全局变量进行猴子修补?
对于我的情况,我将全局变量设置为整个文件的默认记录器,但对于某些特殊功能,我会使用装饰器来更改记录器并添加一些额外信息。
如以下代码:
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()
的日志不会转到记录器 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
这不是线程安全的;您不仅要为这个函数而且要为整个模块更改全局变量。