python logging 仅特定级别

38 投票
2 回答
33615 浏览
提问于 2025-04-17 06:29

我在用Python的日志模块记录事件。我有两个日志文件,一个用来记录用户信息,另一个是给开发者看的更详细的日志文件。我已经把这两个日志文件的级别设置好了(usr.log = INFO,dev.log = ERROR),但是我不知道怎么限制usr.log文件,只让它记录INFO级别的日志,而不是包括INFO及其以上的所有日志,比如WARNING、ERROR和CRITICAL。

这基本上是我的代码:

import logging

logger1 = logging.getLogger('')
logger1.addHandler(logging.FileHandler('/home/tmp/usr.log')
logger1.setLevel(logging.INFO)
logger2 = logging.getLogger('')
logger2.addHandler(logging.FileHandler('/home/tmp/dev.log')
logger2.setLevel(logging.ERROR)

logging.critical('this to be logged in dev.log only')
logging.info('this to be logged to usr.log and dev.log')
logging.warning('this to be logged to dev.log only')

如果能帮忙就太好了,谢谢你。

2 个回答

7

首先,这个想法有点奇怪,我觉得有点不太对劲。正常情况下,程序运行的情况应该告诉用户,但更重要的事情却不告诉用户,这让我很难理解。日志的级别应该用来表示事情的重要性;如果你有一些信息只是开发者关心,那就应该用其他方式来区分这些信息,比如把它们发送到不同的日志记录器。

不过,话说回来,你可以通过创建一个Filter的子类,来实现对日志记录的任意过滤。在这个子类中,你可以定义一个filter方法,按照你想要的标准来过滤日志,然后把它安装到合适的处理器上。

76

我大体上同意David的看法,但我觉得还有更多需要说明的。用《公主新娘》里的话来说——我觉得你的代码并不是你想的那样。你的代码里有:

logger1 = logging.getLogger('')
...
logger2 = logging.getLogger('')

这意味着logger1logger2是同一个日志记录器,所以当你把logger2的级别设置为ERROR时,其实logger1的级别也会同时被设置成ERROR。要想得到两个不同的日志记录器,你需要给它们提供两个不同的名字。例如:

logger1 = logging.getLogger('user')
...
logger2 = logging.getLogger('dev')

更糟糕的是,你在调用日志模块的critical()info()warning()方法时,期望两个日志记录器都能收到消息。之所以能这样做,是因为你给logger1logger2都用了空字符串作为名字,因此它们不仅是同一个日志记录器,还是根日志记录器。如果你按照我建议的那样给两个日志记录器使用不同的名字,那么你就需要分别对每个日志记录器调用critical()info()warning()方法(也就是说,你需要调用两次,而不是一次)。

我觉得你真正想要的是在一个日志记录器上有两个不同的处理器。例如:

import logging

mylogger = logging.getLogger('mylogger')
handler1 = logging.FileHandler('usr.log')
handler1.setLevel(logging.INFO)
mylogger.addHandler(handler1)
handler2 = logging.FileHandler('dev.log')
handler2.setLevel(logging.ERROR)
mylogger.addHandler(handler2)
mylogger.setLevel(logging.INFO)

mylogger.critical('A critical message')
mylogger.info('An info message')

一旦你做了这个更改,你就可以像David提到的那样使用过滤器。这里有一个简单的过滤器示例:

class MyFilter(object):
    def __init__(self, level):
        self.__level = level

    def filter(self, logRecord):
        return logRecord.levelno <= self.__level

你可以像这样将过滤器应用到两个处理器上:

handler1.addFilter(MyFilter(logging.INFO))
...
handler2.addFilter(MyFilter(logging.ERROR))

这样就可以限制每个处理器只输出指定级别的日志消息。

撰写回答