Python logging模块:别再用print来打印啦~

软件开发中通过日志记录程序的运行情况是一个开发的好习惯,对于错误排查和系统运维都有很大帮助。Python标准库自带日志模块,程序的日志功能直接调用标准库的日志模块即可通过日志,开发者可以清楚的了解发生了哪些事件,包括出现了哪些错误。

日志记录是一种跟踪某些软件运行时发生的事件的方法。 该软件的开发人员在其代码中添加了日志记录调用,以指示发生了某些事件。 事件由描述性消息描述,该消息可以可选地包含变量数据。 事件也具有开发者认为该事件的重要性。 重要性也可以称为级别或严重性。

由标准库模块提供的日志记录API的主要好处是所有Python模块都可以参与日志记录,因此您的应用程序日志可以包括您自己的消息以及与第三方模块的消息集成的消息。

首先,需要知道日志是有等级的。下面列举了五个等级。

日志等级(level) 描述
DEBUG 调试信息,通常在诊断问题的时候用
INFO 普通信息,确认程序按照预期运行
WARNING 警告信息,表示发生意想不到的事,或者指示接下来可能会出现一些问题,但是程序还是继续运行
ERROR 错误信息,程序运行中出现了一些问题,程序某些功能不能执行
CRITICAL 危险信息,一个严重的错误,导致程序无法继续运行

注意:指定了日志等级后,只会显示大于等于所指定日志等级的日志信息!

logging中级别大小:

DEBUG < INFO < WARNING < ERROR < CRITICAL

日志内容是可以自己定制的,包括时间,记录内容等等。这些格式是由formater来定制。下面列举一些formater格式:(加粗的就是常用的)

%(asctime)s 日志时间发生的时间
%(levelname)s 该日志记录的日志级别
%(message)s 日志记录的文本内容
%(name)s 所使用的日志器名称,默认是“root”
%(filename)s 调用日志记录函数的文件
%(funcName)s 调用日志记录函数的函数名
%(lineno)d 调用日志记录函数的代码所在的行号
%(pathname)s 打印当前执行程序的路径,其实就是sys.argv[0]
%(thread)d 打印线程ID
%(process)d 打印进程ID

日常使用中,可以通过创建带有默认FormatterStreamHandler并将其添加到根记录器r,对记录系统进行基本配置。 如果没有为根记录器定义处理程序handler,则debug()info()warning()error()critical()函数将自动调用basicConfig()函数。如果根记录器已经配置了处理程序,则此功能将不执行任何操作,除非将关键字参数force设置为True

logging.basicConfig(**kwargs)

basicConfig()的相关参数列举如下:

Format Description
filename 使用指定文件名创建FileHandler
filemode 如果filename指定,使用filemode打开文件,默认是a,追加
format handler使用指定format string
datefmt 使用指定date/time格式
style 如果指定format,使用为format string使用该style。
level 将root logger级别设置为指定level,默认是logging.WARNING
stream 使用指定stream初始化StreamHandler。和filename不能同时指定
handlers 如果指定,应该是已经创建的可迭代的处理程序handler,并添加到根记录器。 任何尚未设置格式器的处理程序都将被分配此函数中创建的默认格式器。 请注意,此参数与filename或stream不兼容,如果同时存在,则会引发ValueError
force 如果将此关键字参数指定为True,则在执行其他参数指定的配置之前,将删除并关闭附加到根记录程序的所有现有处理程序。

这些都是碎片化的知识,下面直接列举一些实用的例子。

PS:日常使用中,只需要对logging进行一定的配置(根据需要),然后把程序中所有使用print()打印内容换成logging.warning()等函数打印即可。

简单使用

日志内容输出到控制台

import logging

# 设置输出的格式
LOG_FORMAT = "Time:%(asctime)s - Level:%(levelname)s - Message:%(message)s"
# 对logger进行配置——日志等级&输出格式
logging.basicConfig(level=logging.WARNING, format=LOG_FORMAT)

# logging.level(message)创建一条level级别的日志
logging.debug("This is a debug log")
logging.info("This is a info log")
logging.warning("This is a warning log")
logging.error("This is a error log")
logging.critical("This is a critical log")

运行结果如下:

在这里插入图片描述

观察可知,只有大于等于WARNING日志等级的日志信息才进行输出!

注意:logging.basicConfig()只能有一个哦!如果写多条——只有第一条会生效!!!

日志信息保存为文件

上述使用最终日志信息都是在终端输出——电脑一关/程序一关/编辑器一关,日志信息就丢失了! 而且我们实际使用中也不会那样做,所以下面就来来看看如何写入文件!
方法很简单,直接再basicConfig()函数中加入filename参数即可。(这里添加filename参数之后,日志不会输出到控制台,而是只输出到log文件)

import logging

# 设置输出的格式
LOG_FORMAT = "Time:%(asctime)s - Level:%(levelname)s - Message:%(message)s"
# 对logger进行配置——日志等级&输出格式
logging.basicConfig(level=logging.WARNING, format=LOG_FORMAT, filename="train.log")

# logging.level(message)创建一条level级别的日志
logging.debug("This is a debug log")
logging.info("This is a info log")
logging.warning("This is a warning log")
logging.error("This is a error log")
logging.critical("This is a critical log")

运行结果如下:

在这里插入图片描述

basicConfig的调用应先于对debuginfo等的任何调用。由于它是一次性的简单配置工具,因此实际上只有第一个调用会做任何事情:后续调用实际上是无操作。如果您多次运行上述脚本,则连续运行的消息将附加到文件train.log中。 如果您希望每个运行重新开始,而不记得先前运行的消息,则可以通过将上述示例中的调用更改为以下方式来指定filemode参数:

logging.basicConfig(filename='example.log', filemode='w', level=logging.WARNING)

输出将与以前相同,但是不再将日志文件附加到该文件,因此先前运行的消息将丢失。

进阶操作:模块化组件

如果只是简单的使用logging,那么使用上面介绍的方法就可以了,如果要深度定制logging,那么就需要对它有更深的了解!

logging模块提供了模块化组件的方法:

组件 说明
Loggers(日志记录器) 提供程序直接使用的接口
(基操中的logging.basicConfig()就是配置了此组件)
Handlers(日志处理器) 将记录的日志发送到指定的位置(终端打印/保存为文件)
Filters(日志过滤器) 用于过滤特定的日志记录
Formatters(日志格式器) 用于控制日志信息的输出格式

模块化组件的使用步骤:

  1. 创建一个logger(日志记录器)对象;
  2. 定义handler(日志处理器),决定把日志发到哪里;常用的是:
    1. StreamHandler——>输出到控制台;
    2. FileHandler——>输出到文件;
  3. 设置日志级别(level)和输出格式Formatters(日志格式器);
  4. 把handler添加到对应的logger中去。

下面列举两个例子,也即是上面例子的升级版。

日志信息保存为文件

import logging

# 1.创建一个logger(日志记录器)对象;
my_logger = logging.Logger("first_logger")

# 2.定义handler(日志处理器),决定把日志发到哪里;
my_handler = logging.FileHandler('test.log')

# 3.设置日志级别(level)和输出格式Formatters(日志格式器);
my_handler.setLevel(logging.INFO)
my_format = logging.Formatter("时间:%(asctime)s 日志信息:%(message)s 行号:%(lineno)d")

# 把handler添加到对应的logger中去。
my_handler.setFormatter(my_format)
my_logger.addHandler(my_handler)


# 使用:
my_logger.info("我是日志组件")

同时写入文件和控制台

在日常使用中,一般我的习惯是同时写入文件和控制台,这样有两个好处:

  • 写入文件避免因为停电或者一些原因导致输出的信息丢失
  • 写入控制台方便查看日志信息
import logging

logger = logging.getLogger("train")

handler = logging.FileHandler('train.log')
handler.setLevel(logging.INFO)
formatter_handler = logging.Formatter("时间:%(asctime)s 日志信息:%(message)s")
handler.setFormatter(formatter_handler)
logger.addHandler(handler)

console = logging.StreamHandler()
console.setLevel(logging.INFO)
format_console = logging.Formatter("时间:%(asctime)s 日志信息:%(message)s 行号:%(lineno)d")
console.setFormatter(format_console)
logger.addHandler(console)

logger.warning("~~~~~哦豁~~~~~")

运行结果如下:

在这里插入图片描述


版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340