python日志模块logging,基础知识和高级知识

logging基本知识

logging是一个python内置的包,即文件夹logging下有一个__init__.py文件

知识点主要包括:

  1. 日志5个级别:logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL
  2. 配置:logging.basicConfig(…)
  3. 配置信息:日志输出文件filename, 日志格式format, 日期格式datefmt, 日志级别level)
  4. 格式信息:%(asctime)s %(levelname)s %(thread)-8d %(name)s %(message)s
  5. 日期格式:%Y-%m-%d %H:%M:%S
  6. logger = logging.getLogger(‘loggername’)这里的loggername即格式中的name
  7. logging.info(msg, args, **kwargs), msg和args可以使用%s一起进行格式化,**kwargs可以填入exc_info=True,这样能够捕获异常信息
日志基础版
# -*- coding:utf-8 -*-
import logging
import traceback


logging.basicConfig(filename='log_learn.log',
                    format='[%(asctime)s] [%(levelname)s] [%(name)s] %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S',
                    level=logging.INFO)

logger = logging.getLogger(__file__)


def division(v):
    return 10/v

# 使用exc_info参数来捕获异常信息,%s可以进行格式化
try:
    division(0)
except:
    logger.error('函数%s报错,报错信息为:', division.__name__, exc_info=1)


# 使用traceback.format_exc()来捕获异常信息
try:
    division(0)
except:
    trace_info = traceback.format_exc()
    msg = '函数{func_name}报错,报错信息为:\n{trace_info}'.format(
            func_name=division.__name__,
            trace_info=trace_info)
    logger.error(msg)

format

 |  %(name)s            Name of the logger (logging channel)
 |  %(levelno)s         Numeric logging level for the message (DEBUG, INFO,
 |                      WARNING, ERROR, CRITICAL)
 |  %(levelname)s       Text logging level for the message ("DEBUG", "INFO",
 |                      "WARNING", "ERROR", "CRITICAL")
 |  %(pathname)s        Full pathname of the source file where the logging
 |                      call was issued (if available)
 |  %(filename)s        Filename portion of pathname
 |  %(module)s          Module (name portion of filename)
 |  %(lineno)d          Source line number where the logging call was issued
 |                      (if available)
 |  %(funcName)s        Function name
 |  %(created)f         Time when the LogRecord was created (time.time()
 |                      return value)
 |  %(asctime)s         Textual time when the LogRecord was created
 |  %(msecs)d           Millisecond portion of the creation time
 |  %(relativeCreated)d Time in milliseconds when the LogRecord was created,
 |                      relative to the time the logging module was loaded
 |                      (typically at application startup time)
 |  %(thread)d          Thread ID (if available)
 |  %(threadName)s      Thread name (if available)
 |  %(process)d         Process ID (if available)
 |  %(message)s         The result of record.getMessage(), computed just as
 |                      the record is emitted

logging高级知识

  • Logger 提供接口给代码,让其操作记录日志
  • Handler 确定日志输出的目的地,可以是文件、控制台等
  • Filter 拒绝不需要的日志内容
  • Formatter 日志内容的格式
日志记录的流程(官网流程图
  1. 代码调用接口如 logger.info
  2. 判断是否满足logger的level,满足则创建LogRecord
  3. Filter是否要拒绝日志,如果不拒绝则进入handler
  4. handler判断日志是否满足level,满足则进行Filter
  5. Filter如果没有拒绝,则emit,进行发出
    在这里插入图片描述
创建3个输出地方的日志记录器
# -*- coding:utf-8 -*-
import logging


# 1、创建日志记录器,使用当前文件路径名作为日志名称,级别为INFO
logger = logging.getLogger(__file__)
logger.setLevel(logging.INFO)

# 2、创建3个日志输出,2个文件,一个控制台
handler_file_1 = logging.FileHandler('file_1.log')
handler_file_1.setLevel(logging.INFO)           # 打印INFO级别及以上的日志信息

handler_file_2 = logging.FileHandler('file_2.log')
handler_file_2.setLevel(logging.ERROR)          # 只打印报错级别及以上的日志信息

handler_stream = logging.StreamHandler()    
handler_stream.setLevel(logging.ERROR)          # 只打印报错级别及以上的日志信息

# 3、创建格式
formatter = logging.Formatter('[%(asctime)s] %(levelname)s %(name)s %(message)s')
handler_file_1.setFormatter(formatter)
handler_file_2.setFormatter(formatter)
handler_stream.setFormatter(formatter)

# 4、操作输出器handler添加到logger
logger.addHandler(handler_file_1)
logger.addHandler(handler_file_2)
logger.addHandler(handler_stream)


def add_value(value):
    logger.info('参数值为:%s', value)
    return value


def division(value):
    try:
        10/value
    except:
        logger.error('发生报错,报错信息为:', exc_info=1)


add_value(0)
division(0)

使用dictConfig来简化上边的操作(功能内容并非完全一致,仅供参考)

# -*- coding:utf-8 -*-
import logging
from logging import config

log_config = {
    'version': 1,
    'loggers': {
        '': {
            'handlers': ['file', 'stream'],
            'level': 'INFO',
        }
    },
    'handlers': {
        'file': {
            'class': 'logging.FileHandler',
            'filename': 'log/log_config.log',
            'level': 'INFO',
            'formatter': 'default'
        },
        'stream': {
            'class': 'logging.StreamHandler',
            'level': 'INFO',
            'formatter': 'simple'
        }
    },
    'formatters': {
        'default': {
            'format': '[%(asctime)s] %(levelname)s %(pathname)s %(message)s',
            'datefmt': '%Y-%m-%d %H:%M:%S'
        },
        'simple': {
            'format': '[%(asctime)s] %(message)s'
        }
    }
}


logging.config.dictConfig(log_config)
logger = logging.getLogger(__file__)


def add_log(data):
    logger.info('执行函数,打印日志,参数为:%s', data)


def division(v):
    try:
        10/v
    except:
        logger.error('函数报错,报错信息为:', exc_info=1)


add_log(10)
division(0)
dictConfig注意事项:
  1. 编写dictConfig,实际上就是对logging使用logger, handler, filter, formatter的使用,将参数统一写到这里
  2. 第一层的这几个单词要加s:loggers,handlers,formatters
  3. loggers底下的handlers是加s的
  4. handlers底下的formatter是不加s的
  5. loggers底下不能直接写handlers,level,要多一层字典,可以用'':{}的形式(如果命名一个会出现报错,不知道什么原因)
  6. class和level的填写,也是用字符串,就是要加上引号,而不是直接写类和常量。
  7. loggers下的handlers的值是一个列表,如果只有一个handler,也要写成列表形式
  8. delay表示延时,FileHandler默认是False,表示实时写入日志,TimedRotatingHandler默认是True,要改成False才会实时写入日志
日志高级版
# -*- coding:utf-8 -*-
import logging
from logging import config
import os

# 创建log文件夹,使用项目名设置log文件名称
project_name = os.path.dirname(__file__).split('/')[-1]
if not os.path.exists('log'):
    os.mkdir('log')

log_file = 'log/' + str(project_name) + '.log'
log_rotate_file = 'log/' + str(project_name) + '_rotate.log'

log_config = {
    'version': 1,
    'loggers': {
        '': {
            'handlers': ['file', 'rotate_file'],
            'level': 'INFO'
        }
    },
    'handlers': {
        'file': {
            'class': 'logging.FileHandler',     # delay默认是False,实时写入
            'filename': log_file,
            'level': 'INFO',
            'formatter': 'default_fmt'
        },
        'rotate_file': {
            'class': 'logging.handlers.TimedRotatingFileHandler',
            'filename': log_rotate_file,
            'level': 'INFO',
            'formatter': 'default_fmt',
            'when': 'D',
            'interval': 1,          # 配合when使用,1D表示间隔1天就会分割一个日志
            'backupCount': 90,      # 保留90个日志,每天1个,相当于一共保留90天
            'delay': False          # 默认是True,不会实时写入,改成False,就不会推迟,实时写入日志
        }
    },
    'formatters': {
        'default_fmt': {
            'format': '[%(asctime)s] %(levelname)s %(pathname)s:%(lineno)d %(message)s',
            # 'datefmt': '%Y-%m-%d %H:%M:%S'
        },
        'simple_fmt': {
            'format': '[%(asctime)s] %(message)s'
        }
    }
}
logging.config.dictConfig(log_config)
logger = logging.getLogger(__file__)


logger.debug('这是debug信息')
logger.info('这是info信息')
logger.error('这是error信息')


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值