【问题标题】:Python Logging - How To Check If Logger Is EmptyPython Logging - 如何检查 Logger 是否为空
【发布时间】:2023-04-03 20:54:02
【问题描述】:

我刚刚在我的应用程序中实现了日志记录,我想知道是否有一种方法可以检查记录器是否为空。

我的想法是在我的脚本中设置两个处理程序:

  • 一个用于控制台,级别为WARNING
  • 一个用于级别为DEBUG 的文件

在脚本结束时,我需要检查CONSOLE logger 是否为空。这意味着在运行期间,记录了一些带有level >= WARNING 的消息,在这种情况下,我想通过smtp 将调试级别的日志文件发送到我的邮箱。

是否可以在 python 脚本本身内进行此检查,而无需将 shell 重定向到文件?

【问题讨论】:

  • 一种想法是为控制台编写一个自定义处理程序,如果它被调用,则使用atexit.register 来安排通过电子邮件发送日志文件的代码。

标签: python logging is-empty


【解决方案1】:

有一种通用方法可以计算使用装饰器调用函数的次数,您可以查看 here

如果你将这个装饰器包裹在你感兴趣的类调用中,你可以找出每个成员函数被调用了多少次,如下所示:

def counted(fn):
    def wrapper(*args, **kwargs):
        wrapper.called += 1
        return fn(*args, **kwargs)
    wrapper.called = 0
    wrapper.__name__ = fn.__name__
    return wrapper

class MyLogger(logging.Logger, object):

    @counted
    def info(self, *args, **kwargs):
        super(MyLogger, self).info(*args, **kwargs)

    @counted
    def warning(self, *args, **kwargs):
        super(MyLogger, self).warning(*args, **kwargs)

接下来只需像其他任何方式一样设置您的记录器并像往常一样使用它:

log = my_logger.MyLogger('test_logger')
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
log.addHandler(ch)
log.setLevel(logging.DEBUG)

>>> log.info('no big deal')
no big deal
>>> log.info('harmless message')
harmless message
>>> log.warning('oh no')
oh no

>>> log.info.called
2
>>> log.warning.called
1

你需要装饰你想要计算的所有类,所以异常、调试等。

【讨论】:

  • 谢谢你,迈克,我会试试的。这似乎也是一个优雅的解决方案。
  • 我试过了 def init_logger(lid: str): log = MyLogger(str(lid)) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) log.addHandler(ch) log .setLevel(logging.DEBUG) return log log1 = init_logger(1) log2 = init_logger(2) log1.info("INFO 1") print(log2.info.call) --> 1 为什么?
【解决方案2】:

对不起,我忘了完成这个帖子。
按照迈克的想法,我想出了这样的东西:

在一个名为 logset.py 的模块中:

def counted(fn):

    def wrapper(*args, **kwargs):
        wrapper.count += 1
        return fn(*args, **kwargs)
    wrapper.count = 0
    wrapper.__name__ = fn.__name__
    return wrapper

class MyLogger(logging.Logger):

    def __init__(self, name=None, level=logging.NOTSET):
        super(MyLogger, self).__init__(name, level)

    @counted
    def info(self, *args, **kwargs):
        super(MyLogger, self).info(*args, **kwargs)

    @counted
    def warning(self, *args, **kwargs):
        super(MyLogger, self).warning(*args, **kwargs)

    @counted
    def critical(self, msg, *args, **kwargs):
        super(MyLogger, self).warning(*args, **kwargs)

    @counted
    def error(self, *args, **kwargs):
        super(MyLogger, self).warning(*args, **kwargs)

    def logfile(self):
        for h in self.handlers:
            if hasattr(h, 'baseFilename'):
                return h.baseFilename

    def empty(self):
        if self.warning.count or self.critical.count or self.error.count:
            return False
        else:
            return True

    def status(self):
        msg = "WARNINGS:%s ERRORS:%s CRITICAL:%s" % (self.warning.count, self.error.count, self.critical.count)
        return msg

def addLogFile(logger, filepath):

    handler = logging.FileHandler(filepath, "w", encoding=None, delay="true")
    handler.setLevel(logging.DEBUG)
    formatter = logging.Formatter("%(levelname)s\t: %(message)s")
    handler.setFormatter(formatter)
    logger.addHandler(handler)

def addLogConsole(logger):

    handler = logging.StreamHandler()
    handler.setLevel(logging.WARNING)
    formatter = logging.Formatter("%(levelname)s\t: %(message)s")
    handler.setFormatter(formatter)
    logger.addHandler(handler)

def myLog(level=None):

    if not LOGGER.handlers:
        # "Adding Handlers..."
        addLogConsole(LOGGER)
        addLogFile(LOGGER, '#YOUR LOG FILE#')

    return LOGGER

LOGGER = MyLogger("root")

在我的应用程序的启动文件中:

from logset import myLog
.
.
. # Initialize the log
root = myLog()
.
.
. # Do something in your app and at end check :

if not root.empty():
    print "\nProgram has logged some errors, check log : %s" % root.logfile()
    print root.status()
    # now I can send root.logfile() via smtp for further examination

您可以在每个需要记录的模块中重复导入,它总是引用同一个记录器对象:

from logset import myLog
log = myLog()
.
.
.
log.info("Adding something")
log.debug("this var has value : %s" % value)

感谢您的帮助和关注。
恩里科

【讨论】:

    猜你喜欢
    • 2011-12-15
    • 2019-10-13
    • 1970-01-01
    • 2017-11-15
    • 2020-05-29
    • 2018-04-02
    • 2016-04-05
    • 2018-01-08
    • 2020-09-25
    相关资源
    最近更新 更多