使用basicConfig设置作为参数记录装饰器

时间:2014-03-17 22:32:57

标签: python logging decorator

编辑:我重新构建了问题并添加了标题,希望它更容易阅读

问题

我正在尝试向python decorator library中的日志记录装饰器添加一些功能。

我想添加的一个选项是能够通过提供字典作为输入来设置日志记录级别。但是,无论我设置什么级别,它总是返回相同的结果。


测试失败

运行下面的设置代码后,我通过运行以下代码来测试它:

@log_with(setConfig={'level':logging.INFO})
def c(msg):
    print(msg)

c('OMG!!')

返回:

INFO:__main__:Running c


DEBUG:__main__:The following arguments have been received:# <-- This should not be here
('OMG!!',)

The following keyword arguments have been received:
{}


INFO:__main__:Returning c
OMG!!

如果这很重要,我将以便携式,非注册方式使用WinPython 2.7.6。 qtconsole中的测试失败


设置代码

import functools, logging


log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)

class log_with(object):
    '''Logging decorator that allows you to log with a
specific logger or set one up on the go.
'''

    def __init__(self,logger=None,funcentry='Running {}',funcexit='Returning {}',setConfig=None):

        self.logger        = logger
        self.ENTRY_MESSAGE = funcentry
        self.EXIT_MESSAGE  = funcexit
        self.setConfig     = setConfig


    def __call__(self, func):
        '''Returns a wrapper that wraps func.
The wrapper will log the entry and exit points of the function
with specified level.
'''
        # set logger if it was not set earlier
        if not self.logger:
            self.logger = logging.getLogger(func.__module__)
            logging.basicConfig(**self.setConfig)

        @functools.wraps(func)
        def wrapper(*args, **kwds):
            self.logger.info(self.ENTRY_MESSAGE.format(func.__name__)+'\n\n')
            self.logger.debug("The following arguments have been received:\n{}\n\nThe following keyword arguments have been received:\n{}\n\n".format(args,kwds))
            try:
                f_result = func(*args, **kwds)
                self.logger.info(self.EXIT_MESSAGE.format(func.__name__))
                return f_result
            except Exception:
                self.logger.exception("An exception was raised:\n\n")
        return wrapper

我的想法和我尝试过的东西

重置所有处理程序

我尝试通过删除可能存在的所有处理程序来修改装饰器中的if not self.logger循环,即

....
if not self.logger:
    for handler in logging.root.handlers[:]:
        logging.root.removeHandler(handler)
....

基于this SO answer然而这也不起作用,即输出保持不变。

我不懂装饰器和/或记录模块!

我删除了

log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)

再次运行代码。这次根本没有打印到屏幕上的记录消息。对我而言,这意味着if not self.logger方法中的__call__循环出现了问题,即未创建记录器。

我不知道为什么......

1 个答案:

答案 0 :(得分:0)

这是我学到的:

  1. 看起来使用basicConfig()设置一些全局变量进行日志记录。更改日志记录级别似乎在全局范围内更改,而不仅仅是针对此调用。

  2. 将装饰器实现为类还是函数似乎都有所不同。虽然不完全确定,但我相信通过在self.setConfig中实现__init__,我更改了我装饰的所有函数的类。我从我找到的解决方案中推断出这一点,该解决方案将装饰器实现为函数:

  3. 这似乎有用(尽管我对事情的回归顺序感到有些困惑):

    def log_with_func(funcentry='Running {}',funcexit='Returning {}',setConfig=None):
        ENTRY_MESSAGE = funcentry
        EXIT_MESSAGE  = funcexit
        def func(f):
            @functools.wraps(f)
            def wrapper(*args, **kwds):
                for handler in logging.root.handlers[:]:
                    logging.root.removeHandler(handler)
                logger = logging.getLogger(__name__)
                if setConfig:
                    logging.basicConfig(**setConfig)
                else:
                    logging.basicConfig(level=logging.INFO)
                logger.info(ENTRY_MESSAGE.format(f.__name__)+'\n\n')
                logger.debug("The following arguments have been received:\n{}\n\nThe following keyword arguments have been received:\n{}\n\n".format(args,kwds))
                try:
                    f_result = f(*args, **kwds)
                    logger.info(EXIT_MESSAGE.format(f.__name__))
                    return f_result
                except Exception:
                    logger.exception("An exception was raised:\n\n")
            return wrapper
        return func
    

    应用它看起来像这样:

    In [24]: @log_with_func()
        ...: def aa(msg):
        ...:     print(msg + 'from a')
        ...:     
    
    In [25]: @log_with_func(setConfig={'level':logging.DEBUG})
        ...: def bb(msg):
        ...:     print(msg + 'from b')
        ...:     
    
    In [26]: print(aa('OMG!!!'))
        ...: print(bb('OMG!!!'))
        ...: print(aa('OMG!!!'))
        ...: 
    INFO:__main__:Running aa
    
    
    INFO:__main__:Returning aa
    INFO:__main__:Running bb
    
    
    DEBUG:__main__:The following arguments have been received:
    ('OMG!!!',)
    
    The following keyword arguments have been received:
    {}
    
    
    INFO:__main__:Returning bb
    INFO:__main__:Running aa
    
    
    INFO:__main__:Returning aa
    OMG!!!from a
    None
    OMG!!!from b
    None
    OMG!!!from a
    None
    
    In [27]: