当前位置: 首页 > 知识库问答 >
问题:

Python-打印前按级别对日志消息进行排序

郏兴贤
2023-03-14

假设我在Python脚本中有这样的日志设置:

import logging

logging.basicConfig(level=logging.DEBUG, stream=sys.stdout,
                    format='%(asctime)s %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S')
logging.info('info')
logging.error('error...')
logging.debug('debug...')

是否有一种方法可以让它等待打印到stdout,直到脚本完成运行,并在打印之前按级别对日志消息进行排序?

共有3个答案

邹海超
2023-03-14

这里有一种方法,它不涉及事后排序(因此效率更高)。它使用此问题中的单级筛选器,并为每种类型的错误使用单独的处理程序。这样,日志肯定是按类型组织的,只检查字符串以确定日志类型不会有任何问题。

import logging
import cStringIO as StringIO

class SingleLevelFilter(logging.Filter):
    '''This single level logging filter is from https://stackoverflow.com/a/1383365/1460235'''
    def __init__(self, passlevel, reject):
        self.passlevel = passlevel
        self.reject = reject

    def filter(self, record):
        if self.reject:
            return (record.levelno != self.passlevel)
        else:
            return (record.levelno == self.passlevel)

# Use this formatter and logLevel in place of setting the global ones
formatter = logging.Formatter(fmt='%(asctime)s %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S')
globalLogLevel = logging.INFO

# build handlers/ StringIO logs for each type
rootLogger = logging.getLogger()
rootLogger.setLevel(globalLogLevel)
logStrObjList = []
handlers = []
i = 0
for logLevel in [logging.INFO, logging.DEBUG, logging.WARNING, logging.ERROR, logging.CRITICAL]:
    logStrObjList.append(StringIO.StringIO())
    handlers.append(logging.StreamHandler(logStrObjList[i]))
    handlers[i].addFilter(SingleLevelFilter(logLevel, False))
    handlers[i].setFormatter(formatter)
    handlers[i].setLevel(globalLogLevel)
    rootLogger.addHandler(handlers[i])
    i += 1

logging.critical('bad news bears')
logging.info('info')
logging.error('error...')
logging.info('info 2')
logging.debug('debug...')
logging.error('another errooo')
傅英喆
2023-03-14

这是一个非常复杂的过程,但是您可以登录到StringIO对象,拆分行,对行进行排序,然后将结果写入文件。

import logging
import cStringIO as StringIO

logStrObj = StringIO.StringIO()

logging.basicConfig(level=logging.DEBUG, stream=logStrObj,
                    format='%(asctime)s %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S')

logging.info('info')
logging.error('error...')
logging.info('info 2')
logging.debug('debug...')

# sort the contents of logStrObj
logList = logStrObj.getvalue().split('\n')
infoLogList = []
debugLogList = []
warningLogList = []
errorLogList = []
criticalLogList = []
for log in logList:
    if 'INFO' in log:
        infoLogList.append(log)
    elif 'DEBUG' in log:
        debugLogList.append(log)
    elif 'WARNING' in log:
        warningLogList.append(log)
    elif 'ERROR' in log:
        errorLogList.append(log)
    elif 'CRITICAL' in log:
        criticalLogList.append(log)
logList = infoLogList + debugLogList + warningLogList + errorLogList + criticalLogList

# write to a file (or print or whatever you want)
for line in logList:
    print line
牧熙云
2023-03-14

从外观上看,传递到stream的对象只需要有write方法。这意味着您可以创建一个类似列表的对象,在调用write时添加数据——然后您可以在打印之前对类似列表的对象进行简单排序。

import logging

class LogList(list):
   def write(self,data):
       self.append(data)

LL = LogList()
logging.basicConfig(stream = LL,level=logging.DEBUG)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.error('Wow, this is bad')
logging.warning('And this, too')
logging.debug('foobar')
logging.warning('baz')

for line in sorted(LL):
   print line[:-1]

当然,您可能需要使您的排序键多一点,以获得不同的级别。类似的东西:

levels = {'DEBUG':0,'INFO':1,'WARNING':2,'ERROR':3}
LL.sort(key = lambda x: levels[x.split(':')[0]])
 类似资料:
  • 我希望将具有特定记录器名称、特定级别和更高级别(例如和更高级别)的消息记录到特定日志处理程序(例如文件处理程序),同时仍将所有日志消息发送到控制台。Python是2.7版。 到目前为止,我尝试创建了两个记录器: 根记录器 命名记录器 对于根记录器,我附加了,并将日志级别设置为。 然后,我将一个处理程序附加到命名记录器,并将该记录器的级别设置为。 当我现在调用使用命名记录器的模块时,我不再获得传播到

  • 如何只打印信息级别? 我当前的日志正在将所有信息、警告、错误和致命级别打印到控制台——我知道为什么会这样。(因为它们都在信息之上) 有没有一种方法可以指定只将信息级别发送到控制台appender,而不是它上面的所有内容? 目前有以下log4j2 xml:

  • 问题内容: 让我们 我想按日期和时间键对输出进行排序。 非常感谢你。 问题答案: 对于GNU排序: 按月份按第二列排序(这样,“三月”排在“四月”之前) 在数字模式下按第三列排序(因此,“ 9”位于“ 10”之前) 按第四列排序。 请参见手册中的更多详细信息。

  • 问题内容: 使用log4j时,该方法可用,可用于在运行时确定的日志级别记录消息。我们正在利用这个事实和技巧将stderr重定向到特定日志级别的记录器。 slf4j没有我可以找到的通用方法。这是否意味着无法实现上述目的? 问题答案: 无法使用来执行此操作。 我认为缺少此功能的原因是几乎无法构造一个类型,该类型可以有效地映射到幕墙后面所有可能的记录实现中使用的(或等效)类型。另外,设计人员认为您的用例

  • 在我看来,我想要达到的目标是很普通的,但我并没有让它起作用: 根记录器可以记录从其他特定记录器传递的信息消息,但是对于这个特定的记录器,我不希望任何信息消息被向上传递到层次结构上。