日志装饰器不输出调试级别的消息

时间:2021-07-14 15:15:07

标签: python python-decorators

我创建了一个日志函数,它用作参数化日志装饰器。

ImportError                               Traceback (most recent call last) <ipython-input-3-a23308ec3f7c> in <module>()
3 import numpy as np
4 import tensorflow as tf
----> 5 import tensorflow_federated as tff
  6 
  7 np.random.seed(0)

28 frames
/usr/local/lib/python3.7/dist-packages/keras/api/_v2/keras/__init__.py in <module>()
  8 import sys as _sys
  9 
---> 10 from keras import __version__
 11 from keras.api._v2.keras import __internal__
 12 from keras.api._v2.keras import activations

ImportError: cannot import name '__version__' from 'keras' (/usr/local/lib/python3.7/dist-packages/keras/__init__.py)

当我用 logging.CRITICAL 调用它时,我会得到一个日志输出到控制台。

from functools import wraps
import logging

def logged(level, name=None, message=None):
    '''
    Add logging to a function.  
    - level is the logging level.
    - name is the logger
    - message is the log message
    If name and mesage are not provided, the module and function name are used by default.
    '''
    
    def decorate(func):
        logname = name if name else func.__module__
        log = logging.getLogger(logname)
        logmsg = message if message else func.__name__
        ch = logging.StreamHandler()
               
        # create formatter
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

        # add formatter to ch
        ch.setFormatter(formatter)

        # add ch to logger
        log.addHandler(ch)
        
        @wraps(func)
        def wrapper(*args, **kwargs):
            log.log(level,logmsg)
            return(func(*args, **kwargs))
        
        return wrapper
    return decorate

输出:

@logged(logging.CRITICAL,'example')
def spam():
    print('SPAM....!')

spam()

但这根本不向控制台返回任何输出:

2021-07-14 16:10:11,699 - example - CRITICAL - spam

1 个答案:

答案 0 :(得分:0)

您需要调用 log.setLevel。默认值为 logging.WARNING

>>> log.getEffectiveLevel()
30
>>> logging.WARNING
30
>>> log.isEnabledFor(logging.WARNING)
True
>>> log.isEnabledFor(logging.INFO)
False
>>> log.isEnabledFor(logging.DEBUG)
False
>>>

既然您不相信,我将您的代码保存为 orig.py 并将 .setLevel 调用添加到副本中,然后将其保存为 modified.py

这是我机器上打印的内容。


>py orig.py

>py modified.py
2021-07-14 17:11:04,202 - __main__ - DEBUG - add

>fc /n orig.py modified.py
Comparing files orig.py and MODIFIED.PY
***** orig.py
   15:          log = logging.getLogger(logname)
   16:          logmsg = message if message else func.__name__
***** MODIFIED.PY
   15:          log = logging.getLogger(logname)
   16:          log.setLevel(level)
   17:          logmsg = message if message else func.__name__
*****


>

这是完整的修改代码

from functools import wraps
import logging

def logged(level, name=None, message=None):
    '''
    Add logging to a function.  
    - level is the logging level.
    - name is the logger
    - message is the log message
    If name and mesage are not provided, the module and function name are used by default.
    '''
    
    def decorate(func):
        logname = name if name else func.__module__
        log = logging.getLogger(logname)
        log.setLevel(level)
        logmsg = message if message else func.__name__
        ch = logging.StreamHandler()
               
        # create formatter
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

        # add formatter to ch
        ch.setFormatter(formatter)

        # add ch to logger
        log.addHandler(ch)
        
        @wraps(func)
        def wrapper(*args, **kwargs):
            log.log(level,logmsg)
            return(func(*args, **kwargs))
        
        return wrapper
    return decorate
    
@logged(logging.DEBUG)
def add(x,y):
    return x + y

add(1,2)