ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python日志模块的配置和使用

2020-02-22 19:00:35  阅读:234  来源: 互联网

标签:logger logging log Python 模块 日志 message name


日志

一、日志的级别

  • CRITICAL : 50

  • ERROR : 40

  • WARNING : 30

  • INFO : 20

  • DEBUG : 10

  • NOTSET : 0 (无日志记录)

    级别 常量 引用方式
    critical 50 logging.CRITICAL
    error 40 logging.ERROR
    warning 30 logging.WARNING
    info 20 logging.INFO
    debug 10 logging.DEBUG
    noset 0 logging.NOSET

二、日志的流程

logging_flow

logger中的传递

  1. Logger 中的日志先经过等级筛选,将高于设定等级的日志信息创建LogRecord对象。
  2. 在__过滤器__中进行处理。
  3. 传递到处理器
  4. 是否发送至父级日志进行处理

在handler中的传递

  1. 先经过等级筛选
  2. 处理器中的过滤器经行过滤
  3. 发送给响应的处理句柄

三、格式化消息

属性名称 格式 描述
args 不需要格式化。 The tuple of arguments merged into msg to produce message, or a dict whose values are used for the merge (when there is only one argument, and it is a dictionary).
asctime %(asctime)s
created %(created)f Time when the LogRecord was created (as returned by time.time()).
exc_info 不需要格式化。 Exception tuple (à la sys.exc_info) or, if no exception has occurred, None.
filename %(filename)s Filename portion of pathname.
funcName %(funcName)s Name of function containing the logging call.
levelname %(levelname)s Text logging level for the message ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL').
levelno %(levelno)s Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL).
lineno %(lineno)d Source line number where the logging call was issued (if available).
message %(message)s The logged message, computed as msg % args. This is set when Formatter.format() is invoked.
module %(module)s 模块 (filename 的名称部分)。
msecs %(msecs)d Millisecond portion of the time when the LogRecord was created.
msg 不需要格式化。 The format string passed in the original logging call. Merged with args to produce message, or an arbitrary object (see 使用任意对象作为消息).
name %(name)s Name of the logger used to log the call.
pathname %(pathname)s Full pathname of the source file where the logging call was issued (if available).
process %(process)d 进程ID(如果可用)
processName %(processName)s 进程名(如果可用)
relativeCreated %(relativeCreated)d Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.
stack_info 不需要格式化。 Stack frame information (where available) from the bottom of the stack in the current thread, up to and including the stack frame of the logging call which resulted in the creation of this record.
thread %(thread)d 线程ID(如果可用)
threadName %(threadName)s 线程名(如果可用)

四、轮替日志

按数量轮替

# 配置文件中的字典参数
'handler_name':{
    'class':'logging.handlers.RotatingFileHandler',  # 日志轮替的类
    'level':'DEBUG',    # 记录等级
    'formatter':'standard', # 使用的消息格式,填写formatters中的键名
    'filename':log_file_name, # 日志文件路径
    'maxBytes':512, # 单个日志最大体积,单位:字节
    'backupCount':4, # 轮替最多保存数量
    'encoding':'utf-8', # 字符编码
},

按时间轮替

# 配置文件中的字典参数
'handler_name':{
    'class':'logging.handlers.TimedRotatingFileHandler',  # 日志轮替的类
    'level':'DEBUG',    # 记录等级
    'formatter':'standard', # 使用的消息格式,填写formatters中的键名
    'filename':log_file_name, # 日志文件路径
    'when':'S', # 时间单位。
    'interval':10, # 间隔时常
    'backupCount':4, # 轮替最多保存数量
    'encoding':'utf-8', # 字符编码
},

when 是一个字符串,定义了日志切分的间隔时间单位,这是一个枚举类,可选参数如下:
"S":Second 秒
"M":Minutes 分钟
"H":Hour 小时
"D":Days 天
"W":Week day(0 = Monday)
"midnight":Roll over at midnight

五、日志配置

使用方法来配置日志

import logging

# create logger
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)

# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)

# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# add formatter to ch
ch.setFormatter(formatter)

# add ch to logger
logger.addHandler(ch)

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')

使用配置文件来配置日志

.py脚本

import logging
import logging.config

logging.config.fileConfig('logging.conf')

# create logger
logger = logging.getLogger('simpleExample')

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')

配置文件logging.conf:

[loggers]
keys=root,simpleExample

[handlers]
keys=consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=

使用字典来配置日志

  • version - 用数字表示的模式版本,当前有效值只能为1,主要是为了后续配置升级后提供兼容性
  • formatters - 格式化对象,值还是一个dict,该dict的键为格式化对象的id,值为一个dict,存储了formatter对象的配置内容
    • format: None
    • datefmt: None
  • filters - 过滤器对象,逻辑同formatters
    • name: ''
  • handlers - 逻辑同formatters
    • class(必须的): handler类的全限定名
    • level(可选的): handler对象级别
    • formatter(可选的):为formatters中定义的formatter对象id
    • filters(可选的):为一个filter对象的列表,里面存放filters中定义的filter对象id
      也可以存入其他的参数,视实际handler对象而定
  • loggers - 逻辑同formatters,该logger对象的id也是logger name
    • level(可选的):logger对象级别
    • propagate(可选的):logger对象的消息传递设置
    • filters(可选的):为一个filter对象的列表,里面存放filters中定义的filter对象id
    • handlers(可选的):为一个handler对象的列表,里面存放handlers中定义的handler对象id
  • root - 值为dict,存放root这个logger对象的配置,但是propagate这个值对root没用
  • incremental - 该配置文件的配置是否作为已有配置的一个补充,该值默认为False,即覆盖原有配置,如果为True,也不是完全覆盖,因为filter对象和formatter对象是匿名的,无法获取到具体的对象,也就无法修改,但是可以替代logger对象的levelpropagate属性,handler对象的level属性
  • disable_existing_loggers - 是否禁用已存在的logger对象,默认是True,如果incrementalTrue的话,该值就会被忽略

注:上述的id处理loggers里的id用来表示实际logger对象的name以外,其他对象的id只是作一个标识作用,用来表示对象之间的联系

通过字典配置参数调用日志,完整代码:

import os
import logging.config

full_formatter = '[%(asctime)s] - [%(levelname)s] - [%(name)s] - [%(module)s模块:%(lineno)d行] - [%(message)s]'
simple_formatter = '[%(asctime)s] - [%(levelname)s] - [%(name)s] - [%(message)s]'

logdir = os.path.join(os.path.dirname(__file__),'logs')

if not os.path.exists(logdir) or not os.path.isdir(logdir):
    os.mkdir(logdir)

log_file_name = 'default.log'
log_file_name2 = 'common.log'

log_file_name = os.path.join(logdir,log_file_name)
log_file_name2 = os.path.join(logdir,log_file_name2)

LOGGING_DICT = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': full_formatter,
            'datefmt': '%Y-%m-%d %H:%M:%S'
        },
        'simple': {
            'format': simple_formatter
        }
    },
    'filters': {},
    'handlers': {
        'sh': {
            'class': 'logging.StreamHandler',
            'level': 'DEBUG',
            'formatter': 'simple'
        },
        'fh':{
            'class':'logging.handlers.RotatingFileHandler',
            'level':'DEBUG',
            'formatter':'standard',
            'filename':log_file_name,
            'maxBytes':512,
            'backupCount':4,
            'encoding':'utf-8',
        },
        'fth':{
            'class':'logging.handlers.TimedRotatingFileHandler',
            'level':'WARNING',
            'formatter':'standard',
            'filename':log_file_name2,
            'when':'S',
            'interval':3,
            'backupCount':10,
            'encoding':'utf-8',
        }

    },
    'loggers': {
        '': {
            'level': 'DEBUG',
            'handlers': ['sh','fh','fth'],
            'propagate': True,
        }
    }
}

def load_log_cfg():
    logging.config.dictConfig(LOGGING_DICT)
    logger2 = logging.getLogger(__name__)
    return logger2

if __name__ == '__main__':

    import time

    log = load_log_cfg()
    t = time.localtime(1111111111)
    print(t)
    while True:
        log.error('这是一个错误日志')
        log.critical('这是一个致命错误日志')
        log.warning('这是一个警告日志')
        log.info('这是一个信息日志')
        time.sleep(3)

标签:logger,logging,log,Python,模块,日志,message,name
来源: https://www.cnblogs.com/jiaowoxiaoming/p/12346657.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有