【转】python模块分析之logging日志(四)

【转】python模块分析之logging日志(四)

python的logging模块是用来写日志的,是python的标准模块。

系列文章

logging的结构

  • 查看logging的python源码,可知主要有四个类实现功能;
  1. Loggers:提供应用程序直接使用的接口,如相关的配置设置;
  2. Handlers:将Loggers产生的日志传到指定位置,设置日志保存的位置;
  3. Filters:对输出日志进行过滤操作;
  4. Formatters:控制日志的输出格式;

日志记录的级别

  • DEBUG:优先级10,记录调试的详细信息,只在调试时开启;

  • INFO:优先级20,记录普通的消息,包括错误和警告等等;

  • WARNING:优先级30,记录相关的警告信息;

  • ERROR:优先级40,记录错误信息,程序崩溃;

  • CRITICAL:优先级50,记录错误信息;

如果不设置级别的话,默认为warning,系统记录设置的日志级别优先级以上的日志信息。

formatters定义日志的输出格式

%(name)s Logger的名字
%(levelno)s 数字形式的日志级别
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名|
%(funcName)s 调用日志输出函数的函数名|
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮点数表示|
%(relativeCreated)d 输出日志信息时的,自Logger创建以来的毫秒数|
%(asctime)s 字符串形式的当前时间。默认格式是“2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有
%(message)s 用户输出的消息
# 定义一个输出格式的对象
formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s')

日志处理器

  • 常见的处理器有两种:

StreamHandler:用于向控制台打印日志;

FileHandler:用于向日志文件打印日志;

  • 其它的处理器
RotatingHandler:logging.handlers.RotatingHandler;日志回滚方式,支持日志文件最大数量和日志文件回滚
TimeRotatingHandler:logging.handlers.TimeRotatingHandler;日志回滚方式,在一定时间区域内回滚日志文件
SocketHandler:logging.handlers.SocketHandler;远程输出日志到TCP/IP sockets
DatagramHandler:logging.handlers.DatagramHandler;远程输出日志到UDP sockets
SMTPHandler:logging.handlers.SMTPHandler;远程输出日志到邮件地址
SysLogHandler:logging.handlers.SysLogHandler;日志输出到syslog
NTEventLogHandler:logging.handlers.NTEventLogHandler;远程输出日志到Windows NT/2000/XP的事件日志
MemoryHandler:logging.handlers.MemoryHandler;日志输出到内存中的指定buffer
HTTPHandler:logging.handlers.HTTPHandler;通过"GET"或者"POST"远程输出到HTTP服务器

logger的基本使用

import logging
import sys

def get_logger(appname):
    # 获取logger实例,如果参数为空则返回root logger
    logger = logging.getLogger(appname)
    # 指定logger输出格式
    formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s')

    # 设置文件处理器,加载处理格式
    file_handler = logging.FileHandler("test.log")
    file_handler.setFormatter(formatter)

    # 控制台日志
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.formatter = formatter

    # 为logger添加的日志处理器
    logger.addHandler(file_handler)
    logger.addHandler(console_handler)

    # 指定日志的最低输出级别,默认为WARN级别
    logger.setLevel(logging.INFO)


if __name__  == "__main__":
    logger = get_logger('test')
    logger.debug('this is debug info')
    logger.info('this is information')
    logger.warn('this is warning message')
    logger.error('this is error message')
    logger.fatal('this is fatal message, it is same as logger.critical')
    logger.critical('this is critical message')

配置logger的方法

  1. 通过代码进行完整配置,主要是通过getLogger方法实现,但不好修改;
  2. 通过basicConfig方法实现,这种方式快速但不够层次分明;
  3. 通过logging.config.fileConfig(filepath),文件配置。

文件配置详解

# logging.conf

[loggers]    # 定义日志的对象名称是什么,注意必须定义root,否则报错。
keys=root,main

[handlers]  # 定义处理器的名称是什么,可以有多个,用逗号隔开
keys=consoleHandler

[formatters]  # 定义输出格式对象的名称,可以有多个,用逗号隔开
keys=simpleFormatter

[logger_root]  # 配置root对象的日志记录级别和使用的处理器
level=INFO
handlers=consoleHandler

[logger_main] # 配置main对象的日志记录级别和使用的处理器,qualname值得就是日志对象的名字
level=INFO
handlers=consoleHandler
qualname=main
propagate=0  # logger对象把日志记录传递给所有相关的handler的时候,会(逐级向上)寻找这个logger和它所有的父logger的全部handler,propagate=1表示会继续向上搜寻;propagate=0表示停止搜寻,这个参数涉及重复打印的坑。

[handler_consoleHandler] # 配置处理器consoleHandler
class=StreamHandler      
level=WARNING
formatter=simpleFormatter
args=(sys.stdout,)

[formatter_simpleFormatter]  # 配置输出格式过滤器simpleFormatter
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
  • 注意:可以看到logger和Handler都可以设置日志级别,日志输出是取最高级别。

一些细节

  1. logger的继承

logging.getLogger(appname),同一个appname获取到的logger对象是同一个,同时appname.name命名的logger继承了appname的所有的属性,可以不用重新配置logger。

  1. 输出错误信息的方法
try:
    raise
except:
    logger.error('this is error message',exc_info = True)
    # 或
    logger.exception("Failed to open sklearn.txt from logger.exception")

# 设置exc_info为True后,会自动将错误的信息也发送到日志中;
# 直接使用exception实现一样的功能。

监听logger配置更改

  • logging.config.listen(port)函数可以让应用程序在一个socket上监听新的配置信息,达到在运行时改变配置,而不用重启应用程序的目的。
import logging.config  
import logging  
import time

logging.config.fileConfig("logging.conf")  
logger = logging.getLogger("test.listen")

t = logging.config.listen(9999)  
t.setDaemon(True)  
t.start()

try:  
    while True:
        logger.info('running.')
        time.sleep(3)
except (KeyboardInterrupt, SystemExit, Exception):  
    logging.config.stopListening()

猜你喜欢

转载自www.cnblogs.com/langqi250/p/9832136.html