Python日志记录教程展示了如何使用日志记录模块在Python中进行日志记录。

1 介绍

1.1 背景

日志记录是将信息写入日志文件的过程。日志文件包含有关在操作系统,软件或通信中发生的各种事件的信息。完成记录是出于以下目的:

  • 信息收集
  • 故障排除
  • 产生统计资料
  • 审计
  • 剖析

记录不仅限于识别软件开发中的错误。它还可用于检测安全事件,监视策略违规,在出现问题时提供信息,查找应用程序瓶颈或生成使用情况数据。应记录的事件包括输入验证失败,身份验证和授权失败,应用程序错误,配置更改以及应用程序启动和关闭。
但是不应记录的事件包括应用程序源代码,会话标识值,访问令牌,敏感的个人数据,密码,数据库连接字符串,加密密钥,银行帐户和持卡人数据。
综上所述,进行日志记录的一些最佳做法:

  • 日志记录应该有意义。
  • 日志应包含上下文。
  • 日志记录应在不同级别进行结构化和完成。
  • 日志记录应该是平衡的;它不应该包含太少或太多的信息。
  • 记录消息应该是人类可以理解的,并且可以被机器解析。
  • 登录更复杂的应用程序应完成几个日志文件。
  • 日志应适应开发和生产。

1.2 Python日志记录模块

Python日志模块定义了一些函数和类,这些函数和类为应用程序和库实现了一个灵活的事件日志系统。
日志记录模块具有四个主要组件:记录器(loggers),处理程序(handlers),过滤器(filters)和格式化程序(formatters)。记录器公开了应用程序代码直接使用的接口。处理程序将日志记录(由记录器创建)发送到适当的目的地。筛选器提供了更细粒度的功能,用于确定要输出的日志记录。格式化程序在最终输出中指定日志记录的布局。
Python日志记录级别主要有以下六个:

  • CRITICAL 危急
  • ERROR 错误
  • WARNING 警告
  • INFO 信息
  • DEBUG 调试
  • NOTSET 无设置

要注意日志等级是从上到下依次降低的,即:NOTEST< DEBUG < INFO < WARNING < ERROR < CRITICAL,而日志的信息量是依次减少的;
如果日志记录级别设置为WARNING,所有的WARNING, ERROR以及CRITICAL消息被写入日志文件或控制台。如果它被设置为ERROR,只有ERROR和 CRITICAL消息被记录。

日志记录器具有有效等级的概念。如果未在记录器上显式设置级别,则将其父级别用作其有效级别。如果父级没有显式设置的级别,则检查其父级,依此类推-搜索所有祖先,直到找到显式设置的级别。使用getLogger()创建记录器时,级别设置为NOTSET。如果未使用set level()显式设置日志记录级别,则消息将传播到日志记录父级。在找到级别不是NOTSET的祖先或到达根记录器之前,将遍历日志记录器的祖先链。根记录器设置了默认警告级别。

1.3 根记录器

所有记录器都是根记录器的后代。每个记录器将日志消息传递到其父级。使用该getLogger(name) 方法创建新的记录器。调用不带名称的函数(getLogger())将返回root记录器。根记录器始终具有显式级别集,WARNING 默认情况下为该级别。
根记录器位于层次结构的顶部,并且始终存在,即使未配置。通常,程序或库不应直接针对根日志记录器进行日志记录。相反,应该为程序配置一个特定的记录器。根日志可以用来轻松地打开和关闭所有库中的所有日志。

2 Python logging模块使用教程

python logging模块通常可以直接调用,无需安装

2.1 Python logging模块简单使用

该logging模块具有简单的方法,无需任何配置即可立即使用。这可以用于简单的日志记录。以下示例调用该logging模块的五个方法。消息将写入控制台。请注意,使用了根记录器,并且只写入了三则消息。这是因为默认情况下,仅写入具有级别警告和更高级别的消息。

import logging

logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')
WARNING:root:This is a warning message
ERROR:root:This is an error message
CRITICAL:root:This is a critical message

2.2 Python有效日志记录级别

日志记录级别是用set level()设置的。它将此记录器的阈值设置为lvl。将忽略严重程度低于lvl的日志消息。在下面示例中,我们将日志记录级别更改为DEBUG。

getLogger()返回具有指定名称的记录器。如果name为None,则返回根记录器。名称可以是定义日志层次结构的点分隔字符串;例如“a”、“a.b”或“a.b.c”。

import logging

# getLogger()返回具有指定名称的记录器。如果name为None,则返回根记录器。
logger = logging.getLogger('dev')
# 设置debug级别
logger.setLevel(logging.DEBUG) logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger.critical('This is a critical message')
DEBUG:dev:This is a debug message
INFO:dev:This is an info message
WARNING:dev:This is a warning message
ERROR:dev:This is an error message
CRITICAL:dev:This is a critical message

2.3 Python有效日志记录级别

有效日志记录级别是显式设置的级别或由日志记录父级确定的级别。每一个日志级别都有与之对应的一个阈值,如果日志级别对应的阈值小于设定值,就不会显示出来。各级别阈值为:

  • CRITICAL = 50
  • ERROR = 40
  • WARNING = 30
  • INFO = 20
  • DEBUG = 10
  • NOTSET = 0

以下示例中,我们检查了两个记录器的有效记录级别。

import logging

main_logger = logging.getLogger('main')
# 设定级别
main_logger.setLevel(logging.ERROR) # 未设置dev_logger的级别;然后使用其父级的级别。
dev_logger = logging.getLogger() print(main_logger.getEffectiveLevel())
print(dev_logger.getEffectiveLevel())
40
30

2.4 Python记录处理程序

处理程序是一个对象,负责将适当的日志消息(基于日志消息的严重性)分派到处理程序的指定目标。处理程序像级别一样设定。如果记录器没有处理程序集,则其父记录器将搜索处理程序。

以下示例为记录器创建了两个处理程序:文件处理程序和控制台处理程序。

import logging

logger = logging.getLogger('dev')
logger.setLevel(logging.INFO) # 文件处理
# FileHandler将日志记录发送到test.log 文件。
fileHandler = logging.FileHandler('test.log')
fileHandler.setLevel(logging.INFO) # 控制台处理
# StreamHandler将日志记录发送到流。如果未指定控制流,r则使用sys.stder。
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.INFO) # 将处理程序添加到记录器addHandler()。
logger.addHandler(fileHandler)
logger.addHandler(consoleHandler) # 打印数据,并且保存数据
logger.info('information message')
information message
INFO:dev:information message

注意上面的程序在添加到记录器必须移除处理程序(这是这个大坑),不然会重复输出,因为会把当前logger和其父节点所有数据输出,如下所示:

import logging

logger = logging.getLogger('dev')
logger.setLevel(logging.INFO) # 文件处理
# FileHandler将日志记录发送到test.log 文件。
fileHandler = logging.FileHandler('test.log')
fileHandler.setLevel(logging.INFO) # 控制台处理
# StreamHandler将日志记录发送到流。如果未指定控制流,r则使用sys.stder。
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.INFO) # 将处理程序添加到记录器addHandler()。
logger.addHandler(fileHandler)
logger.addHandler(consoleHandler) # 打印数据,并且保存数据
logger.info('information message')
information message
information message
INFO:dev:information message

解决办法在记录日志之后通过removeHandler移除处理函数

https://www.cnblogs.com/telecomshy/p/10630888.html

https://blog.csdn.net/huilan_same/article/details/51858817

import logging

logger = logging.getLogger('dev')
logger.setLevel(logging.INFO) # 文件处理
# FileHandler将日志记录发送到test.log 文件。
fileHandler = logging.FileHandler('test.log')
fileHandler.setLevel(logging.INFO) # 控制台处理
# StreamHandler将日志记录发送到流。如果未指定控制流,r则使用sys.stder。
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.INFO) # 将处理程序添加到记录器addHandler()。
logger.addHandler(fileHandler)
logger.addHandler(consoleHandler) # 打印数据,并且保存数据
logger.info('information message') # 移除处理函数
logger.removeHandler(fileHandler)
logger.removeHandler(consoleHandler) # 关闭处理函数
# 不然文件无法删除
# 返回输出只有三个information message输出
fileHandler.close();
consoleHandler.close();
information message
information message
information message
INFO:dev:information message

2.5 Python记录格式化程序

格式化程序是配置日志记录的最终顺序、结构和内容的对象。除了消息字符串之外,日志记录还包括日期和时间、日志名称和日志级别的严重性。下面示例创建一个控制台记录器,并向其处理程序添加格式化程序。

import logging

logger = logging.getLogger('devs')
logger.setLevel(logging.INFO) consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.INFO) logger.addHandler(consoleHandler) # 创建格式化程序。它包括日期时间,记录器名称,记录级别名称和记录消息。
formatter = logging.Formatter('%(asctime)s %(name)s %(levelname)s: %(message)s')
consoleHandler.setFormatter(formatter) logger.info('information message') logger.removeHandler(consoleHandler)
consoleHandler.close;
2020-06-23 22:57:06,591  devs  INFO: information message
INFO:devs:information message

2.6 Python日志基本配置

basicConfig()配置根记录器。它通过使用默认格式化程序创建流处理程序来完成日志系统的基本配置。如果没有为根记录器定义处理程序,则debug()、info()、warning()、error()和critical()将自动调用basicConfig()。

以下示例使用basicConfig来配置根记录器。

import logging

# filename保存日志,format格式化输出,level设定消息等级
# 运行该程序后,我们在test.log文件中写入了五条消息 。
logging.basicConfig(filename='test.log', format='%(filename)s: %(message)s',
level=logging.DEBUG) logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')
WARNING:root:This is a warning message
ERROR:root:This is an error message
CRITICAL:root:This is a critical message

2.7 Python日志记录文件配置

fileConfig()从configparser格式文件读取日志配置。本文在log.conf定义了一个记录器,处理程序和格式化。

log.conf文件内容如下:

[loggers]
keys=root,dev [handlers]
keys=consoleHandler [formatters]
keys=extend,simple [logger_root]
level=INFO
handlers=consoleHandler [logger_dev]
level=INFO
handlers=consoleHandler
qualname=dev
propagate=0 [handler_consoleHandler]
class=StreamHandler
level=INFO
formatter=extend
args=(sys.stdout,) [formatter_extend]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s [formatter_simple]
format=%(asctime)s - %(message)s

以下示例从log.conf中读取日志记录配置文件。

import logging
import logging.config logging.config.fileConfig(fname='log.conf') logger = logging.getLogger('dev')
logger.info('This is an information message')
2020-06-23 22:57:06,617 - dev - INFO - This is an information message

2.8 Python日志记录变量

通过使用字符串格式记录动态数据。以下示例将自定义数据写入日志消息。

import logging

root = logging.getLogger()
root.setLevel(logging.INFO) log_format = '%(asctime)s %(filename)s: %(message)s'
logging.basicConfig(filename="test.log", format=log_format) # incident happens
# 将自定义数据写入日志消息。
error_message = 'authentication failed' root.error(f'error: {error_message}')
2020-06-23 22:57:06,624 - root - ERROR - error: authentication failed

2.9 Python日志记录格式日期时间

日期时间包含在带有asctime日志记录的日志消息中。使用datefmt配置选项,我们可以格式化datetime字符串。以下示格式化日志消息的日期时间。

import logging

logger = logging.getLogger()
logger.setLevel(logging.DEBUG) log_format = '%(asctime)s %(filename)s: %(message)s'
logging.basicConfig(filename="test.log", format=log_format,
datefmt='%Y-%m-%d %H:%M:%S') logger.info("information message")
2020-06-23 22:57:06,631 - root - INFO - information message

2.10 Python日志记录堆栈跟踪

堆栈跟踪是调用函数的堆栈,这些函数一直运行到引发异常时为止。堆栈跟踪包含在exc_info选项中。
以下示例中,我们记录了尝试访问不存在的列表索引时引发的异常。

import logging

log_format = '%(asctime)s %(filename)s: %(message)s'
logging.basicConfig(filename="test.log", format=log_format) vals = [1, 2] try:
print(vals[4]) except Exception as e:
# 通过将exc_info设置为True,堆栈跟踪将包含在日志中。
logging.error("exception occurred", exc_info=True)
2020-06-23 22:57:06,638 - root - ERROR - exception occurred
Traceback (most recent call last):
File "<ipython-input-12-ef7fe4bd5d82>", line 9, in <module>
print(vals[4])
IndexError: list index out of range

2.11 Python记录getLogger

在getLogger()返回具有指定名称的记录器。如果未指定名称,则返回根记录器。通常的做法是将模块名称放在其中。

使用给定名称对此函数的所有调用都返回相同的记录器实例。这意味着记录器实例不需要在应用程序的不同部分之间传递(这一点很坑)。

以下示例使用getLogger()创建一个新的记录器。它有一个文件处理程序和一个格式化程序

import logging
import sys main = logging.getLogger('main')
main.setLevel(logging.DEBUG) # 消息将被写入 my.log文件
handler = logging.FileHandler('my.log') format = logging.Formatter('%(asctime)s %(name)s %(levelname)s: %(message)s')
handler.setFormatter(format) main.addHandler(handler) main.info('info message')
main.critical('critical message')
main.debug('debug message')
main.warning('warning message')
main.error('error message') # 清除数据
main.removeHandler(handler)
handler.close();

my.log中内容如下:

2020-06-23 22:54:41,265  main    INFO: info message
2020-06-23 22:54:41,265 main CRITICAL: critical message
2020-06-23 22:54:41,265 main DEBUG: debug message
2020-06-23 22:54:41,265 main WARNING: warning message
2020-06-23 22:54:41,265 main ERROR: error message

3 参考

http://zetcode.com/python/logging/

https://www.cnblogs.com/telecomshy/p/10630888.html

https://blog.csdn.net/huilan_same/article/details/51858817

[编程基础] Python日志记录库logging总结的更多相关文章

  1. [编程基础] Python谷歌翻译库googletrans总结

    1 使用说明 本文介绍python谷歌翻译库接口googletrans的使用.具体见官方文档: https://py-googletrans.readthedocs.io/en/latest/#goo ...

  2. Python日志记录(logging)

    import logging logfile = 'e:\\a.txt' # logging.basicConfig(filename=logfile,level=logging.INFO) # lo ...

  3. [编程基础] Python数据生成库Faker总结

    Python Faker教程展示了如何使用Faker软件包在Python中生成伪数据.我们使用joke2k/faker包. 1 介绍 Faker是一个生成假数据的Python库.伪数据通常用于测试或用 ...

  4. [编程基础] Python配置文件读取库ConfigParser总结

    Python ConfigParser教程显示了如何使用ConfigParser在Python中使用配置文件. 文章目录 1 介绍 1.1 Python ConfigParser读取文件 1.2 Py ...

  5. Python 日志记录与程序流追踪(基础篇)

    日志记录(Logging) More than print: 每次用 terminal debug 时都要手动在各种可能出现 bug 的地方 print 相关信息来确认 bug 的位置: 每次完成 d ...

  6. 基于java.util.logging实现轻量级日志记录库(增加根据当前类class初始化,修复线程池模型(javaEE)下的堆栈轨迹顺序与当前调用方法不一致问题)

    前言: 本章介绍自己写的基于java.util.logging的轻量级日志记录库(baseLog). 该版本的日志记录库犹如其名,baseLog,是个实现日志记录基本功能的小库,适合小型项目使用,方便 ...

  7. python 日志打印之logging使用介绍

    python 日志打印之logging使用介绍 by:授客QQ:1033553122 测试环境: Python版本:Python 2.7   简单的将日志打印到屏幕 import logging lo ...

  8. 十:SpringBoot-配置AOP切面编程,解决日志记录业务

    SpringBoot-配置AOP切面编程,解决日志记录业务 1.AOP切面编程 1.1 AOP编程特点 1.2 AOP中术语和图解 2.SpringBoot整合AOP 2.1 核心依赖 2.2 编写日 ...

  9. golang常用库:日志记录库-logrus使用

    介绍 logrus 它是一个结构化.插件化的日志记录库.完全兼容 golang 标准库中的日志模块.它还内置了 2 种日志输出格式 JSONFormatter 和 TextFormatter,来定义输 ...

随机推荐

  1. Oracle安装和卸载

    Oracle安装: 1. 检查是否安装net framework 3.5 2. 安装win64_11gR2_database服务端 更改安装目录,设置密码 2. 检查服务 services.msc,两 ...

  2. How to get the return value of the setTimeout inner function in js All In One

    How to get the return value of the setTimeout inner function in js All In One 在 js 中如何获取 setTimeout ...

  3. 【杂谈】2021-CSP退役记

    Part1:复赛前一周 感觉复赛来的好快...... 我还没 颓够 准备好就来了QAQ 根据模拟赛 爆零 的光辉事迹,这次复赛我特别慌,虽然但是还是不想复习 但无所谓了,复赛一下子就只剩一天了 Par ...

  4. 基于win11安装Java11环境

    下载JDK解压版本 下载后解压,并放到一个没有中文路径的目录,如图所示: 配置Java环境变量 以Windows11系统为例,打开设置,搜索"环境",点击"编辑系统环境变 ...

  5. 基于tauri+vue3.x多开窗口|Tauri创建多窗体实践

    最近一种在捣鼓 Tauri 集成 Vue3 技术开发桌面端应用实践,tauri 实现创建多窗口,窗口之间通讯功能. 开始正文之前,先来了解下 tauri 结合 vue3.js 快速创建项目. taur ...

  6. springboot项目中使用shiro实现用户登录以及权限的验证

    欢迎大家加入我的社区:http://t.csdn.cn/Q52km 社区中不定时发红包 更加高级的验证用户权限:用户表.角色表.权限表.多表联合:https://blog.csdn.net/weixi ...

  7. python求列表均值,方差,标准差

    import numpy as np a = [1,2,3,4,5,6] #求均值 a_mean = np.mean(a) #求方差 a_var = np.var(a) #求标准差 a_std = n ...

  8. Mockito使用方法(Kotlin)

    一.为什么要使用Mockito 1.实际案例 1.1 遇到的问题 对于经常维护的项目,经常遇到一个实际问题:需求不停改变,导致架构经常需要修改某些概念的定义. 对于某些十分基础又十分常用的概念,常常牵 ...

  9. 初识Rasp——Openrasp代码分析

    初识Rasp--Openrasp代码分析 @author:Drag0nf1y 本文首发于奇安信安全社区,现转载到个人博客. 原文链接: https://forum.butian.net/share/1 ...

  10. Rust Aya 编写 eBPF 程序

    本文地址:https://www.ebpf.top/post/ebpf_rust_aya 1. 前言 Linux 内核 6.1 版本中有一个非常引人注意的变化:引入了对 Rust 编程语言的支持.Ru ...