python之logging模块

我们在日常的代码中,经常需要将系统运行过程中的一些错误,或者用户操作步骤记录到日志文件中,所以我们要完成这些记录就会用到logging模块。

一、logging模块的基本用法

import logging
import sys

# 获取logger实例,如果参数为空则返回root logger
logger = logging.getLogger("AppName")

# 指定logger输出格式
formatter = logging.Formatter('%(asctime)s %(levelname)-8s: %(message)s')

# 文件日志
file_handler = logging.FileHandler("test.log")
file_handler.setFormatter(formatter)  # 可以通过setFormatter指定输出格式

# 控制台日志
console_handler = logging.StreamHandler(sys.stdout)
console_handler.formatter = formatter  # 也可以直接给formatter赋值

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

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

# 输出不同级别的log
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')

# 2017-09-29 22:21:37,250 INFO    : this is information
# 2017-09-29 22:21:37,250 WARNING : this is warning message
# 2017-09-29 22:21:37,250 ERROR   : this is error message
# 2017-09-29 22:21:37,251 CRITICAL: this is fatal message, it is same as logger.critical
# 2017-09-29 22:21:37,251 CRITICAL: this is critical message

# 移除一些日志处理器
logger.removeHandler(file_handler)

格式化输出日志

GetLogger()方法

            这是最基本的入口,该方法参数可以为空,默认的logger名称是root,如果在同一个程序中一直都使用同名的logger,其实会拿到同一个实例,使用这个技巧就可以跨模块调用同样的logger来记录日志。同时我们可以使用不同的日志名称来区分不同模块,如下图所示

logger = logging.getLogger("App.web")
logger = logging.getLogger("App.server")

Formatter格式化

Formatter对象定义了log信息的结构和内容,构造时需要带两个参数,分别为fmt和datefmt。

  • fmt是格式化模板,默认包含了最基本的level和message信息
  • datefmt是格式化的时间样式,默认为%Y-%m-%d %H:%M:%S

fmt可以使用的变量

%(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 用户输出的消息

SetLevel 日志级别

Logging有如下级别: DEBUG,INFO,WARNING,ERROR,CRITICAL
默认级别是WARNING,logging模块只会输出指定level以上的log。这样的好处, 就是在项目开发时debug用的log,在产品release阶段不用一一注释,只需要调整logger的级别就可以。

Handler 日志处理器

最常用的是StreamHandler和FileHandler, Handler用于向不同的输出端打log。Logging包含很多handler, 可能用到的有下面几种

  1. StreamHandler instances send error messages to streams (file-like objects).
  2. FileHandler instances send error messages to disk files.
  3. RotatingFileHandler instances send error messages to disk files, with support for maximum log file sizes and log file rotation.
  4. TimedRotatingFileHandler instances send error messages to disk files, rotating the log file at certain timed intervals.
  5. SocketHandler instances send error messages to TCP/IP sockets.
  6. DatagramHandler instances send error messages to UDP sockets.
  7. SMTPHandler instances send error messages to a designated email address.

Configuration 配置方法

logging的配置大致有下面几种方式。

  1. 通过代码进行完整配置,可以参考开头的例子,主要是通过getLogger方法实现。
  2. 通过代码进行简单配置,下面有例子,主要是通过basicConfig方法实现。
  3. 通过配置文件,下面有例子,主要是通过 logging.config.fileConfig(filepath)

logging.basicConfig

basicConfig()提供了非常便捷的方式让你配置logging模块并马上开始使用。通过对日志系统进行基本配置,指定一些可以修改的参数。默认的行为是创建一个StreamHandler,它将写入sys.stderr,通过使用使用BASIC_FORMAT来格式化字符串,并将处理程序添加到根日志记录器。

可配置参数:

filename  使用指定的文件名,而不是一个StreamHandler来创建文件处理程序

filemode  如果指定了文件名,则指定打开文件的模式(如果filemode未指定,则默认为“a”)

format    为处理程序使用指定的格式字符串

datefmt   使用指定的日期/时间格式,同time.strftime()

style     如果指定了格式字符串,请使用它来指定类型的格式字符串

level     将日志记录器级别设置为指定级别

stream    使用指定的流来初始化StreamHandler。注意,此参数与“filename”不兼容
          如果两者都存在,“stream”将被忽略。

handlers  如果指定,这应该是已经创建的处理程序的迭代,它将被添加到根处理程序中。
          列表中没有分配格式化程序的任何处理程序将被分配在这个函数中创建的格式化程序。

使用示例

import logging

logging.basicConfig(level=logging.INFO,
            format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
            datefmt='%a, %d %b %Y %H:%M:%S',
            filename='test.log',
            filemode='w')

logging.info('test this log')

#Sat, 30 Sep 2017 11:07:40 logger.py test this log

logging.config模块配置日志

#logger.conf
###############################################
[loggers]
keys=root,example01,example02
[logger_root]
level=DEBUG
handlers=hand01,hand02
[logger_example01]
handlers=hand01,hand02
qualname=example01
propagate=0
[logger_example02]
handlers=hand01,hand03
qualname=example02
propagate=0
###############################################
[handlers]
keys=hand01,hand02,hand03
[handler_hand01]
class=StreamHandler
level=INFO
formatter=form02
args=(sys.stderr,)
[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form01
args=('myapp.log', 'a')
[handler_hand03]
class=handlers.RotatingFileHandler
level=INFO
formatter=form02
args=('myapp.log', 'a', 10*1024*1024, 5)
###############################################
[formatters]
keys=form01,form02
[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s
datefmt=%a, %d %b %Y %H:%M:%S
[formatter_form02]
format=%(name)-12s: %(levelname)-8s %(message)s
datefmt=

使用示例

import logging
from logging import config

config.fileConfig("logging.config")
logger = logging.getLogger("example01")

logger.debug('This is debug message')
logger.info('This is info message')
logger.warning('This is warning message')

 

发表评论

电子邮件地址不会被公开。