Python日志系统logging使用介绍

日志记录对于软件开发调试和运行都非常重要。Python标准库提供了一个日志记录系统,可以很方便的在python项目中添加日志记录。本文将详细介绍如何使用python的 logging 模块来记录日志。

目录

基础使用 日志级别 基本配置 保存日志到文件 格式化输出 捕获异常信息自定义logger 日志模块四大组件 处理器 格式器 过滤器 示例其他配置方法 fileConfig()方法 dictConfig()方法 1. yaml配置文件 2. json配置文件

基础使用

日志级别

主要包括了5种日志级别,代表5种严重级别(严重程度由低到高):

  • DEBUG:提供详细的详细

  • INFO:程序运行的关键步骤信息

  • WARNING:警告信息

  • ERROR:程序错误,某个功能无法执行

  • CRITICAL:严重错误,可能整个程序无法执行

Logger提供了一个默认的记录器,称为root Logger。

import logging``   ``logging.debug('Debug 级别日志信息')``logging.info('Info 级别日志信息')``logging.warning('Warning 级别日志信息')``logging.error('Error 级别日志信息')``logging.critical('Critical 级别日志信息')

输出:

WARNING:root:Warning 级别日志信息``ERROR:root:Error 级别日志信息``CRITICAL:root:Critical 级别日志信息

默认打印WARNING及更高严重级别的日志。

基本配置

可以使用basicConfig(**kwargs)方法对日志系统进行配置。常用参数如下:

  • level: 指定严重级别。

  • filename: 指定文件。

  • filemode: 如果指定了filename,则以该模式打开文件。默认是a,表示追加。

  • a:追加

  • w:覆盖

  • format:日志信息的格式。默认levelname, name和message属性,用冒号分隔。

注意:basicConfig函数只能被调用一次。

level参数可以设置要记录的日志消息的严重级别:

import logging``   ``logging.basicConfig(level=logging.DEBUG)``   ``logging.debug('Debug 级别日志信息')``logging.info('Info 级别日志信息')``logging.warning('Warning 级别日志信息')``logging.error('Error 级别日志信息')``logging.critical('Critical 级别日志信息')

输出:

DEBUG:root:Debug 级别日志信息``INFO:root:Info 级别日志信息``WARNING:root:Warning 级别日志信息``ERROR:root:Error 级别日志信息``CRITICAL:root:Critical 级别日志信息

保存日志到文件

import logging``   ``logging.basicConfig(filename='test.log', filemode='w', format='%(name)s - %(levelname)s - %(message)s')``logging.debug('Debug 级别日志信息')``logging.info('Info 级别日志信息')``logging.warning('Warning 级别日志信息')``logging.error('Error 级别日志信息')``logging.critical('Critical 级别日志信息')

格式化输出

format 参数用于格式化输出设置,除了默认设置levelname, name和message属性:

属性名使用格式描述
asctime%(asctime)s时间,默认格式为 ‘2003-07-08 16:49:45,896’
created%(created)f时间戳
relativeCreated%(relativeCreated)d相对于加载日志模块的时间(以毫秒为单位)。
msecs%(msecs)d日志创建时间的毫秒部分
filename%(filename)s脚本文件名称
funcName%(funcName)s调用日志记录的函数名称
module%(module)s脚本模块名
pathname%(pathname)s脚本文件绝对路径名
name%(name)s记录器名称,默认logger名为root
levelname%(levelname)s文本类型的日志级别 ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL').
levelno%(levelno)s数字类型的日志级别 (10, 20, 30, 40, 50).
lineno%(lineno)d日志调用的代码所在行号
message%(message)s日志信息
process%(process)d进程ID
processName%(processName)s进程名称
thread%(thread)d线程ID
threadName%(threadName)s线程名

其中 asctime 时间格式可以使用 datefmt 属性更改,语法格式与python datetime模块的格式化函数相同,例如:

import logging``   ``logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(message)s', datefmt='%Y%m%d-%H:%M:%S')``   ``logging.debug('Debug 级别日志信息')``logging.info('Info 级别日志信息')``logging.warning('Warning 级别日志信息')``logging.error('Error 级别日志信息')``logging.critical('Critical 级别日志信息')

输出:

20230228-22:13:05 - Debug 级别日志信息``20230228-22:13:05 - Info 级别日志信息``20230228-22:13:05 - Warning 级别日志信息``20230228-22:13:05 - Error 级别日志信息``20230228-22:13:05 - Critical 级别日志信息

除了以上属性外,还支持自定义属性,使用 extra 参数传递:

import logging``   ``FORMAT = '%(asctime)s - %(clientip)s - %(message)s'``logging.basicConfig(format=FORMAT)``clientip = '192.168.0.1'``d = {'clientip':clientip}``   ``logging.info('Info 级别日志信息')``logging.warning('Warning 级别日志信息', extra=d)

输出:

2023-03-04 11:21:23,459 - 192.168.0.1 - Warning 级别日志信息

捕获异常信息

设置 exc_info 参数为 True 可以输出信息报错信息:

import logging``   ``try:`  `res = 1 / 0``except Exception as e:`  `logging.error(e, exc_info=True)

输出:

ERROR:root:division by zero``Traceback (most recent call last):`  `File "d:\logging\log_demo3.py", line 4, in <module>`    `res = 1 / 0``ZeroDivisionError: division by zero

也可以使用 logging.exception() 方法,效果一样:

logging.exception(e)

另外,stack_info 参数设置为 True 是可以打印堆栈信息。

自定义logger

可以通过创建logger类的对象来定义自己的记录器。

日志模块四大组件

日志模块最常用的类:

  • Logger:公开了一个接口,代码通过使用该接口记录日志消息。

  • Handler:处理器,将logger创建的日志发送到目的地(控制台或文件)。常用的处理程序包括:

  • FileHandler:用于将日志消息发送到文件

  • StreamHandler:用于向输出流(如stdout)发送日志消息

  • SyslogHandler:用于向syslog守护进程发送日志消息

  • HTTPHandler:用于使用HTTP协议发送日志消息

  • Filter:过滤器,提供一种机制来确定记录哪些日志。

  • Formatter:格式器,决定日志消息的输出格式。

Logger类是入口,使用模块级别函数 logging.getLogger(name) 实例化,最终由Handler来对日志进行处理,Handler会调用Filter和Formatter来对日志进行过滤和格式化。

import logging``   ``logger = logging.getLogger('mylogger')``   ``logger.debug('Debug 级别日志信息')``logger.info('Info 级别日志信息')``logger.warning('Warning 级别日志信息')``logger.error('Error 级别日志信息')``logger.critical('Critical 级别日志信息')

自定义logger不能使用 basicConfig() 来配置,需要使用 处理器(Handler)和 格式器(Formatter)来配置。

处理器

可以使用处理器(Handler)来配置自定义logger将日志保存到文件、输出到控制台、通过HTTP发送或者通过邮件发送。

处理器也可以设置日志严重级别,为文件处理器(FileHandler)和控制台处理器(StreamHandler)设置不同的日志级别。

# 创建处理器 handlers``console_handler = logging.StreamHandler() # 输出到控制台``file_handler    = logging.FileHandler(logname) # 输出到文件``console_handler.setLevel(logging.WARNING)``file_handler.setLevel(logging.ERROR)

格式器

格式器(Formatter)用来配置格式化输出。

# 创建格式器``console_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s', '%Y%m%d-%H:%M:%S')``file_format    = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', '%Y%m%d-%H:%M:%S')

过滤器

过滤器(Filter)可实现日志过滤操作,

import logging``import sys``import os``   ``class failureFilter(logging.Filter):`    `def filter(self, record):`        `if 'Failure' in record.msg:`            `return True`        `return False``   ``logger = logging.getLogger(__name__)`  `console_handler = logging.StreamHandler(stream=sys.stdout) # 输出到控制台``# 添加filter``loggingFiletr = failureFilter()``console_handler.addFilter(loggingFiletr)``   ``logger.addHandler(console_handler)``logger.info('Info 级别日志信息')``logger.error('Failure')

示例

自定义logger示例脚本:

import logging``import sys``import os``   ``class failureFilter(logging.Filter):`    `def filter(self, record):`        `if 'Failure' in record.msg:`            `return True`        `return False``   ``logger = logging.getLogger(__name__)``logger.setLevel(logging.INFO)``   ``abspath = os.path.dirname(os.path.abspath(__file__)) # 脚本绝对路径``logname = os.path.join(abspath, 'file.log')``   ``# 创建处理器 handlers``console_handler = logging.StreamHandler(stream=sys.stdout) # 输出到控制台``file_handler    = logging.FileHandler(logname) # 输出到文件``console_handler.setLevel(logging.WARNING)``file_handler.setLevel(logging.ERROR)``   ``# 添加filter``loggingFiletr = failureFilter()``console_handler.addFilter(loggingFiletr)``file_handler.addFilter(loggingFiletr)``   ``# 创建格式器``console_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s', '%Y%m%d-%H:%M:%S')``file_format    = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', '%Y%m%d-%H:%M:%S')``   ``# 将格式器添加到处理器中``console_handler.setFormatter(console_format)``file_handler.setFormatter(file_format)``   ``# 将处理器添加到logger``logger.addHandler(console_handler)``logger.addHandler(file_handler)``   ``logger.info('Info 级别日志信息')``logger.error('Failure')

其他配置方法

除了前面介绍的 basicConfig() 方法、logger、handler和formatter来配置日志记录器外,还可以使用 fileConfig()dictConfig() 方法来加载配置文件或字典实现日志记录器的配置。

fileConfig()方法

配置文件(可使用configparser类读取)格式如下,此配置文件配置了控制台和文件输出两种方式:

[loggers]``keys=root,mylogger``   ``[handlers]``keys=consoleHandler,fileHandler``   ``[formatters]``keys=sampleFormatter``   ``[logger_root]``level=DEBUG``handlers=consoleHandler``   ``[logger_mylogger]``level=DEBUG``handlers=consoleHandler,fileHandler``qualname=mylogger``propagate=0``   ``[handler_consoleHandler]``class=StreamHandler``level=DEBUG``formatter=sampleFormatter``args=(sys.stdout,)``   ``[handler_fileHandler]``class=FileHandler``level=DEBUG``formatter=sampleFormatter``args=("config.log", "a")``   ``[formatter_sampleFormatter]``format=%(asctime)s - %(name)s - %(levelname)s - %(message)s``qualname=mylogger

使用 fileConfig 方法来加载配置:

import logging``import logging.config``import os``   ``abspath = os.path.dirname(os.path.abspath(__file__))` `confpath = os.path.join(abspath, 'logging.conf')``   ``if os.path.exists(confpath):`    `logging.config.fileConfig(fname=confpath, disable_existing_loggers=False)``   ``# create logger``logger = logging.getLogger("mylogger")``   ``logger.debug('Debug 级别日志信息')``logger.info('Info 级别日志信息')

dictConfig()方法

配置字典可以使用yaml或者json代码来编写。

1. yaml配置文件

创建logging.yaml

version: 1``formatters:`  `simple:`    `format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'`    `datefmt: '%Y-%m-%d %H:%M:%S'``handlers:`  `console:`    `class: logging.StreamHandler`    `level: INFO`    `formatter: simple`    `stream: ext://sys.stdout`  `fileHandler:`    `class: logging.FileHandler`    `level: DEBUG`    `formatter: simple`    `filename: yaml.log`    `encoding: utf8``loggers:`  `mylogger:`    `level: DEBUG`    `handlers: [console,fileHandler]`    `propagate: no``root:`  `level: DEBUG`  `handlers: [console]

调用示例:

import logging``import logging.config``import os``import yaml``   ``abspath = os.path.dirname(os.path.abspath(__file__))``confpath = os.path.join(abspath, 'logging.yaml')``   ``if os.path.exists(confpath):`    `with open(confpath, 'r') as f:`        `config = yaml.safe_load(f.read())`    `logging.config.dictConfig(config)``   ``logger = logging.getLogger('mylogger')``   ``logger.debug('Debug 级别日志信息')``logger.info('Info 级别日志信息')

2. json配置文件

创建logging.json

{`    `"version":1,`    `"disable_existing_loggers":false,`    `"formatters":{`        `"simple":{`            `"format":"%(asctime)s - %(name)s - %(levelname)s - %(message)s",`            `"datefmt":"%Y-%m-%d %H:%M:%S"`        `}`    `},`    `"handlers":{`        `"console":{`            `"class":"logging.StreamHandler",`            `"level":"DEBUG",`            `"formatter":"simple",`            `"stream":"ext://sys.stdout"`        `},`        `"fileHandler":{`            `"class":"logging.handlers.RotatingFileHandler",`            `"level":"INFO",`            `"formatter":"simple",`            `"filename":"json.log",`            `"maxBytes":10485760,`            `"backupCount":10,`            `"encoding":"utf8"`        `}`    `},`    `"loggers":{`        `"mylogger":{`            `"level":"INFO",`            `"handlers":["fileHandler"],`            `"propagate":"no"`        `}`    `},`    `"root":{`        `"level":"INFO",`        `"handlers":["console","fileHandler"]`    `}``}

调用示例:

import logging``import logging.config``import os``import json``   ``abspath = os.path.dirname(os.path.abspath(__file__))` `confpath = os.path.join(abspath, 'logging.json')``   ``if os.path.exists(confpath):`    `with open(confpath, 'r') as f:`        `config = json.load(f)`    `logging.config.dictConfig(config)``   ``logger = logging.getLogger("mylogger")``   ``logger.debug('Debug 级别日志信息')``logger.info('Info 级别日志信息')

点击下方安全链接前往获取

CSDN大礼包:《Python入门&进阶学习资源包》免费分享

👉Python实战案例👈

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

图片

图片

👉Python书籍和视频合集👈

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

图片

👉Python副业创收路线👈

图片

这些资料都是非常不错的,朋友们如果有需要《Python学习路线&学习资料》,点击下方安全链接前往获取

CSDN大礼包:《Python入门&进阶学习资源包》免费分享

本文转自网络,如有侵权,请联系删除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值