Python中的logging模块

news2024/11/8 21:35:50

软件开发中通过日志记录程序的运行情况是一个开发的好习惯,对于错误排查和系统运维都有很大帮助。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

日常使用中,可以通过创建带有默认Formatter的StreamHandler并将其添加到根记录器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的调用应先于对debug,info等的任何调用。由于它是一次性的简单配置工具,因此实际上只有第一个调用会做任何事情:后续调用实际上是无操作。如果您多次运行上述脚本,则连续运行的消息将附加到文件train.log中。 如果您希望每个运行重新开始,而不记得先前运行的消息,则可以通过将上述示例中的调用更改为以下方式来指定filemode参数:

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

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

进阶操作:模块化组件

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

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

组件

说明

Loggers(日志记录器)

提供程序直接使用的接口

(基操中的logging.basicConfig()就是配置了此组件)

Handlers(日志处理器)

将记录的日志发送到指定的位置(终端打印/保存为文件)

Filters(日志过滤器)

用于过滤特定的日志记录

Formatters(日志格式器)

用于控制日志信息的输出格式

模块化组件的使用步骤:

  1. 创建一个logger(日志记录器)对象;

  1. 定义handler(日志处理器),决定把日志发到哪里;常用的是:

  • StreamHandler——>输出到控制台;

  • FileHandler——>输出到文件;

  1. 设置日志级别(level)和输出格式Formatters(日志格式器);

  1. 把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("~~~~~哦豁~~~~~")

运行结果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/185435.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux随记(五)

一、已用statefulset创了两个nginx副本 web-0 和 web-1 &#xff0c;目的将各自容器的hostname重定向到index.html。但显示的是master节点的hostname。 怎么写才是搞成 pod里面的主机名&#xff1f;#最终解决方法&#xff1a; 在sh -c 双引号里$符号前面加上\转义。 或者 sh -…

Redis原理篇(二)网络模型

一、用户空间和内核空间 应用需要通过Linux内核与硬件交互。 内核本质也是应用&#xff0c;运行的时候也需要CPU资源、内存资源。用户应用也在消耗这些资源。 为了避免用户应用导致冲突甚至内核崩溃&#xff0c;用户应用与内核是分离的&#xff1a; 进程的寻址空间会划分为两…

《安富莱嵌入式周报》第301期:ThreadX老大离开微软推出PX5 RTOS第5代系统,支持回流焊的自焊接PCB板设计,单色屏实现多级灰度播放视频效果

往期周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 祝大家开工大吉 视频版&#xff1a; https://www.bilibili.com/video/BV1GT411o7zr 1、ThreadX老大离开微软&…

又一个开源工具搞完了,工作效率直接翻倍

&#x1f3e1; 博客首页&#xff1a;派 大 星 ⛳️ 欢迎关注 &#x1f433; 点赞 &#x1f392; 收藏 ✏️ 留言 &#x1f3a2; 本文由派大星原创编撰 &#x1f6a7; 系列专栏&#xff1a;《开源专栏》 &#x1f388; 本系列主要输出作者自创的开源项目 &#x1f517; 作品&…

JavaScript switch 语句

JavaScript switch 语句 switch 语句评估一个表达式&#xff0c;将表达式的值与case子句匹配&#xff0c;并执行与该情况相关联的语句。 举例说明 const expr Papayas; switch (expr) {case Oranges:console.log(Oranges are $0.59 a pound.);break;case Mangoes:case Papa…

力扣刷题|104.二叉树的最大深度、559.n 叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数

文章目录LeetCode 104.二叉树的最大深度题目链接&#x1f517;思路LeetCode 111.二叉树的最小深度题目链接&#x1f517;思路LeetCode 222.完全二叉树的节点个数题目链接&#x1f517;普通二叉树求法针对完全二叉树解法LeetCode 104.二叉树的最大深度 题目链接&#x1f517; …

WebAssembly 助力 桌面端运行web

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.WebAssembly 是基…

缺陷分析测试人员绕不开的知识点

缺陷分析也是测试工程师需要掌握的一个能力&#xff0c;但是很多时候大家只记得要提交缺陷、统计缺陷情况&#xff0c;而忽视了缺陷分析。 其实每个项目的缺陷记录都是有很大价值的。在测试阶段分析当前缺陷情况&#xff0c;及时发现存在的问题并调整测试策略&#xff0c;才能…

区间一维dp史上最细总结(绝对干货,还不会的一定要进来)

那年初夏&#xff08;三&#xff09; 注&#xff1a;此部分仅为娱乐和引入用&#xff0c;与本文没有太大关联&#xff0c;可以跳过&#xff0c;阅读下面的正文部分。 上篇出现于&#xff1a;DFS&#xff08;深度优先搜索&#xff09;详解&#xff08;概念讲解&#xff0c;图片…

HashSet源码分析

一、HashSet继承关系 1、继承 public boolean equals(Object o) {if (o this)return true;// o没有实现Set接口&#xff0c;返回falseif (!(o instanceof Set))return false;// 向下转换Collection<?> c (Collection<?>) o;// 元素个数不相等&#xff0c;返回f…

4.组件通讯

默认情况下组件只能使用自己的状态&#xff0c;但当组件拆分的比较小的时候&#xff0c;就不可避免的使用到其他组件的状态&#xff0c;比如之前做的例子&#xff0c;当我们的发表评论区域与显示评论区域拆分为两个组件时&#xff0c;这两个组件之间一定要进行通讯以达成某些功…

π122M30代替Si8621AB-B-IS 低功耗,高能效、抗干扰能力好的 双通道数字隔离器解决方案

π122M30代替Si8621AB-B-IS 低功耗&#xff0c;高能效、抗干扰能力好的解决方案电路简单、稳定性更高 &#xff0c;具有出色的性能特征和可靠性&#xff0c;整体性能优于光耦和基于其他原理的数字隔离器产品。 产品传输通道间彼此独立&#xff0c;可实现多种传输方向的配置&…

Day11 C++STL入门基础知识八——stack、queue容器 基本概念-常用接口 【全面深度剖析+例题代码展示】

&#x1f483;&#x1f3fc; 本人简介&#xff1a;男 &#x1f476;&#x1f3fc; 年龄&#xff1a;18 &#x1f6a9; 今日留言&#xff1a;亮亮被迫去练科目二啦&#xff0c;定时发布的文章&#xff0c;回来统一给大家三连回复嗷~&#x1f609; 文章目录1. stack容器——栈1.…

CSDN常见问题汇总

1.怎么申请退款&#xff1f; 通过CSDN平台购买的“VIP会员、余额”&#xff0c;在刚购买后未使用的情况可支持退款&#xff1b; “付费资源、付费专栏、盲盒、魔盒、课程、C认证”等虚拟商品一经购买后&#xff0c;除了特殊原因外&#xff0c;概不支持退款&#xff1b; 特殊原…

美团8年测试经验,一文手把手教你抒写接口测试框架集成测试报告

在接口自动化测试完成后&#xff0c;通常我们都需要一个测试报告来进行结果展示&#xff0c;而测试报告的美观程度直接决定了你在同事和领导眼中的技术形象&#xff0c;本文将介绍rest-assured接口测试框架集成ExtentReports测试报告&#xff0c;让你的框架更加完美。 ExtentR…

【大唐杯备考】——5G网元功能与接口(学习笔记)

&#x1f4d6; 前言&#xff1a;本期介绍5G网元功能与接口。 目录&#x1f552; 1. 5G移动通信系统整体网络架构&#x1f558; 1.1 5G核心网架构&#x1f558; 1.2 5G接入网架构&#x1f552; 2. 5G主要网元功能&#x1f558; 2.1 UPF&#xff08;用户面功能&#xff09;&#…

使用code-server为Docker容器搭建在线开发环境

Code-server是一个基于服务端的开源VSCode。只要服务器端配置好code-server&#xff0c;就可以在任何浏览器上使用VScode访问服务器的代码进行编程。&#xff08;GitHub地址&#xff1a;https://github.com/cdr/code-server&#xff09; Docker是一个开源的Linux容器引擎。我们…

DeepLabV3+:搭建Mobilenetv2网络

目录 Mobilenetv2的介绍 Mobilenetv2的结构 Inverted Residual Block倒残差结构 Pytorch实现Inverted Residual Block 搭建Mobilenetv2 Pytorch实现Mobilenetv2主干网络 相关参考资料 Mobilenetv2的介绍 Mobilenetv2网络设计基于Mobilenetv1&#xff0c;它保持了其简单…

【进击的算法】动态规划——01背包

&#x1f37f;本文主题&#xff1a;动态规划 01背包 背包问题 C/C 算法 &#x1f388;更多算法&#xff1a;基础回溯算法 基础动态规划 &#x1f495;我的主页&#xff1a;蓝色学者的主页 文章目录一、前言二、概念✔️动态规划概念✔️01背包的概念三、问题描述与讲解&#x1…

spring 中 mybaits 的一级缓存失效

mybatis 的一级缓存 简单回顾下mybatis的一级缓存 本质上是一个基于map实现的内存级别的缓存&#xff0c;默认开启&#xff0c;生命周期是 sqlsession 级别的 为什么会失效 其实这个问题反向分析一下就会有思路了&#xff0c;一级缓存默认是sqlsession级别的&#xff0c;这个规…