[python logging]日志记录模块

2023-11-04

logging 介绍

Logger从来不直接实例化,经常通过logging模块级方法(Module-Level Function)logging.getLogger(name)来获得,其中如果name不给定就用root。

名字是以点号分割的命名方式命名的(a.b.c)。对同一个名字的多个调用logging.getLogger()方法会返回同一个logger对象。这种命名方式里面,后面的loggers是前面logger的子logger,自动继承父loggers的log信息,正因为此,没有必要把一个应用的所有logger都配置一遍,只要把顶层的logger配置好了,然后子logger根据需要继承就行了。

Logger对象扮演了三重角色:

首先,它暴露给应用几个方法(logger.info(),logger.debug(),...)以便应用可以在运行时写log.

其次,Logger对象按照log信息的严重程度(信息等级)或者根据filter对象来决定如何处理log信息(默认的信息过滤功能).

最后,logger还负责把log信息传送给相关的handlers(信息处理功能).

logging框架中主要由四个部分组成:

  • Loggers: 可供程序直接调用的接口(logger.info(),logger.debug(),...)

  • Handlers: 决定将日志记录分配至正确的目的地(file,stream,emile,...)

  • Filters: 提供更细粒度的日志是否输出的判断

  • Formatters: 制定最终记录打印的格式布局(信息记录内容有哪些及格式)

loggers

loggers 就是程序可以直接调用的一个日志接口,可以直接向logger写入日志信息。logger并不是直接实例化使用的,而是通过logging.getLogger(name)来获取对象,事实上logger对象是单例模式,logging是多线程安全的,也就是无论程序中哪里需要打日志获取到的logger对象都是同一个。但是不幸的是logger并不支持多进程,这个在后面的章节再解释,并给出一些解决方案。

【注意】loggers对象是有父子关系的,当没有父logger对象时它的父对象是root,当拥有父对象时父子关系会被修正。举个例子logging.getLogger("abc.xyz")会创建两个logger对象,一个是abc父对象,一个是xyz子对象,同时abc没有父对象所以它的父对象是root。但是实际上abc是一个占位对象(虚的日志对象),可以没有handler来处理日志。但是root不是占位对象,如果某一个日志对象打日志时,它的父对象会同时收到日志,所以有些使用者发现创建了一个logger对象时会打两遍日志,就是因为他创建的logger打了一遍日志,同时root对象也打了一遍日志。

每个logger都有一个日志的级别。

当一个logger收到日志信息后先判断是否符合level,如果决定要处理就将信息传递给Handlers进行处理。

Handlers

Handlers 将logger发过来的信息进行准确地分配,送往正确的地方。举个栗子,送往控制台或者文件或者both或者其他地方(进程管道之类的)。它决定了每个日志的行为,是之后需要配置的重点区域。

每个Handler同样有一个日志级别,一个logger可以拥有多个handler也就是说logger可以根据不同的日志级别将日志传递给不同的handler。当然也可以相同的级别传递给多个handlers这就根据需求来灵活的设置了。

Filters

Filters 提供了更细粒度的判断,来决定日志是否需要打印。原则上handler获得一个日志就必定会根据级别被统一处理,但是如果handler拥有一个Filter可以对日志进行额外的处理和判断。例如Filter能够对来自特定源的日志进行拦截or修改甚至修改其日志级别(修改后再进行级别判断)。

logger和handler都可以安装filter甚至可以安装多个filter串联起来。

Formatters

Formatters 指定了最终某条记录打印的格式布局。Formatter会将传递来的信息拼接成一条具体的字符串,默认情况下Format只会将信息%(message)s直接打印出来。Format中有一些自带的LogRecord属性可以使用,如下表格:

一个Handler只能拥有一个Formatter 因此如果要实现多种格式的输出只能用多个Handler来实现。

基本使用

配置logging基本的设置,然后在控制台输出日志

import logging

# 配置全局config,可以设置不同的信息等级
# level = logging.DEBUG,INFO,WARNING,ERROR,CRITICAL严重程度一次递增。
# format : 信息记录格式
logging.basicConfig(level = logging.INFO,
                    format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')

logger = logging.getLogger(__name__)

logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")

logging.basicConfig的参数

filename:指定日志文件名;
filemode:和file函数意义相同,指定日志文件的打开模式,'w'或者'a';
format:指定输出的格式和内容,format可以输出很多有用的信息 # '%(asctime)s - %(name)s - %(message)s'
datefmt:指定时间格式,同time.strftime(), # %Y-%m-%d %H:%M:%S
level:设置日志级别,默认为logging.WARNNING;
stream:指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略; 

format的格式说明

logging.Foamatter(fmt='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

属性名称

格式

说明

name

%(name)s

日志的名称

asctime

%(asctime)s

可读时间,默认格式‘2003-07-08 16:49:45,896’,逗号之后是毫秒

filename

%(filename)s

文件名,pathname的一部分

pathname

%(pathname)s

文件的全路径名称

funcName

%(funcName)s

调用日志多对应的方法名

levelname

%(levelname)s

日志的等级

levelno

%(levelno)s

数字化的日志等级

lineno

%(lineno)d

被记录日志在源码中的行数

module

%(module)s

模块名

msecs

%(msecs)d

时间中的毫秒部分

process

%(process)d

进程的ID

processName

%(processName)s

进程的名称

thread

%(thread)d

线程的ID

threadName

%(threadName)s

线程的名称

relativeCreated

%(relativeCreated)d

日志被创建的相对时间,以毫秒为单位

handler的种类

可以发现,logging有一个日志处理的主对象,其他处理方式都是通过addHandler添加进去,logging中包含的handler主要有如下几种,
StreamHandler:logging.StreamHandler;日志输出到流,可以是sys.stderr,sys.stdout或者文件
FileHandler:logging.FileHandler;日志输出到文件
BaseRotatingHandler:logging.handlers.BaseRotatingHandler;基本的日志回滚方式
RotatingHandler:logging.handlers.RotatingHandler;日志回滚方式,支持日志文件最大数量和日志文件回滚
TimeRotatingHandler:logging.handlers.TimeRotatingHandler;日志回滚方式,在一定时间区域内回滚日志文件
SocketHandler:logging.handlers.SocketHandler;远程输出日志到TCP/IP sockets
DatagramHandler:logging.handlers.DatagramHandler;远程输出日志到UDP sockets
SMTPHandler:logging.handlers.SMTPHandler;远程输出日志到邮件地址
SysLogHandler:logging.handlers.SysLogHandler;日志输出到syslog
NTEventLogHandler:logging.handlers.NTEventLogHandler;远程输出日志到Windows NT/2000/XP的事件日志
MemoryHandler:logging.handlers.MemoryHandler;日志输出到内存中的指定buffer
HTTPHandler:logging.handlers.HTTPHandler;通过"GET"或者"POST"远程输出到HTTP服务器

消息的等级

FATAL:致命错误
CRITICAL:特别糟糕的事情,如内存耗尽、磁盘空间为空,一般很少使用
ERROR:发生错误时,如IO操作失败或者连接问题
WARNING:发生很重要的事件,但是并不是错误时,如用户登录密码错误
INFO:处理请求或者状态变化等日常事务
DEBUG:调试过程中使用DEBUG等级,如算法中每个循环的中间状态

对应数值

级别

数值

CRITICAL

50

ERROR

40

WARNING

30

INFO

20

DEBUG

10

NOTSET

0

将日志写入到文件示例

创建一个FileHandler,并对输出消息的格式进行设置,将其添加到logger,然后将日志写入到指定的文件中

import logging

# 初始化一个logger
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)

# 创建FileHandler
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

# 记录信息
logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")

将日志同时输出屏幕和日志文件示例

logger中添加StreamHandler,可以将日志输出到屏幕上

import logging

# 初始化一个logger
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)

# 创建FileHandler
filehandler = logging.FileHandler("log.txt")
filehandler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
filehandler.setFormatter(formatter)
logger.addHandler(filehandler)

# stream
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter(datefmt='%Y/%m/%d %H:%M:%S',
                              fmt='[ %(asctime)s ] %(message)s')
console.setFormatter(formatter)
logger.addHandler(console)

# 记录信息
logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")

捕获traceback示例

Python中的traceback模块被用于跟踪异常返回信息,可以在logging中记录下traceback

设置 exc_info = True

import logging

# 初始化一个logger
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)

# 创建FileHandler
filehandler = logging.FileHandler("log.txt")
filehandler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
filehandler.setFormatter(formatter)
logger.addHandler(filehandler)

# stream
console = logging.StreamHandler()
console.setLevel(logging.INFO)
logger.addHandler(console)

# 记录信息
logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")

# 配合try except使用,捕获异常。
try:
    open("sklearn.txt","rb")
except (SystemExit, KeyboardInterrupt):
    raise
except Exception:
    logger.error("Faild to open sklearn.txt from logger.error", exc_info = True)
 
logger.info("Finish")

缓存技术加速[颜色显示]示例

"""
Modified from https://github.com/microsoft/Swin-Transformer/blob/main/logger.py
"""
 
import os
import sys
import logging
import functools
from termcolor import colored  # 命令行颜色
 
 
@functools.lru_cache()  # 使用缓存技术,加快处理速度
def create_logger(output_dir, dist_rank=0, name=""):
    # create logger
    logger = logging.getLogger(name)  # 也可以是__name__ is the module’s name 
    logger.setLevel(logging.DEBUG)
    logger.propagate = False
 
    # create formatter
    fmt = "[%(asctime)s %(name)s] (%(filename)s %(lineno)d): %(levelname)s %(message)s"
    color_fmt = (
        colored("[%(asctime)s %(name)s]", "green")
        + colored("(%(filename)s %(lineno)d)", "yellow")
        + ": %(levelname)s %(message)s"
    )
 
    # create console handlers for master process
    if dist_rank == 0:
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setLevel(logging.DEBUG)
        console_handler.setFormatter(
            logging.Formatter(fmt=color_fmt, datefmt="%Y-%m-%d %H:%M:%S")
        )
        logger.addHandler(console_handler)
 
    # create file handlers
    file_handler = logging.FileHandler(
        os.path.join(output_dir, f"log_rank{dist_rank}.txt"), mode="a"
    )
    file_handler.setLevel(logging.DEBUG)
    file_handler.setFormatter(logging.Formatter(fmt=fmt, datefmt="%Y-%m-%d %H:%M:%S"))
    logger.addHandler(file_handler)
 
    return logger


特此说明:仅仅作为自己学习记录使用,防止忘记了,收藏的太多以免找不到,所有权归作者所有。

主要参考(超级详细):Python logger模块 - 浅雨凉 - 博客园 (cnblogs.com)

logging介绍部分:python logging 日志模块以及多进程日志_程序员大咖的博客-CSDN博客

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[python logging]日志记录模块 的相关文章

随机推荐

  • Maven 编译遇到 Process terminated【四种情况全部解决】

    情况一 配置文件 settings xml 出错 解决方法1 1 1 项目编译报错如下 1 2 点击 项目名 提示找到出错文件 1 3 点击查看出错文件 在idea中打开了settings文件 找到提示的报错位置 1 4 原因及解决办法 原
  • Altium中网络标签、端口、离图以及编译范围的设置区别?

    1 Altium Designer多图纸功能 原理图主次分层次 Altium Designer多图纸功能 原理图主次分层次 1 1 各类网络标识符 由于我们使用到多图纸功能 这时需要考虑图纸间的线路连接 在单个图纸中 我们可以通过简单的网络
  • pandas数据处理大全(必备)

    目录 文章目录 目录 pandas读取文件 pandas存储文件 pandas处理空值和缺失值 pandas创建空dataframe dataframe索引值的修改 dataframe选择行与列 dataframe转置 dataframe添
  • Nodejs 中的非阻塞I/O、异步和事件驱动

    前言 Node js使用 事件驱动机制 具有非阻塞的I O模型这样的特点 Node js中的大多数Api都用到了异步函数 那麽又该如何获取异步函数返回的数据呐 废话不多说 来看看本次分享 都有哪些亮点吧 一 Nodejs 的 非阻塞 I O
  • 使用VS2019 开发Linux C++ 程序

    第一步 注 如果Windows下面查询不到dns也可以不设置静态IP地址 直接跳到第二步 1 先将自己的Linux 系统设为静态IP 具体操作如下 修改 etc network interfaces 地址配置文件 如下所示 操作 代码 修改
  • 网络存储ISCSI详解

    一 网络存储 目前应用最为广泛的两种数据存储设备 NAS与SAN 1 NAS NAS的全称是Network attached storage 即网络附加存储 并不需要单独的网络用于存储IO 更适用于中小型的存储解决方案 NAS设备通常是一个
  • 关于PID的输入输出是什么--供自己复习使用

    本人也是个新手 最近对平衡车感兴趣 所以恶补了一些关于pid的知识 下面是关于pid的文章 后续在平衡车上有进展也会出一些关于平衡车的文章 第一次写文章 有许多的不足之处 希望给位网友给予指正 在过程控制中 按偏差的比例 P 积分 I 和微
  • Linux文件解压缩:tar: /xxx: Not found in archive

    因为压缩文件使用的相对路径 如果在解压是使用绝对路径需要加上 C指令 tar zxvf xxx tar gz C usr local apps
  • 5G到底厉害在什么地方?和4G有什么不同?

    5G给大家的第一个印象肯定就是速度很快 秒下电影 这也是媒体大力宣传的一个点 5G的速度的确比4G快了很多 但是5G不仅仅是速度大大提高了 还有其他更重要的优点 不知道你有没有这种感觉 4G的速度已经挺快了啊 我们手机看视频一点都不卡啊 有
  • mpvue中小程序版本更新

    在App vue中 onLaunch if wx canIUse getUpdateManager const updateManager wx getUpdateManager updateManager onCheckForUpdate
  • Server-Sent Events 一种轻量级的Push方式

    文章目录 SSE工作原理 SSE的特点 SSE的推送数据格式 SSE的使用 客户端 服务端 效果展示 简单来说 Server Sent Events 简称SSE 是服务端发送事件 即服务端Push的一种机制 SSE工作原理 一般来说HTTP
  • 封装NavLink组件

    之后可以通过
  • 后继者:找出二叉搜索树中指定节点的“下一个”节点

    后继者 设计一个算法 找出二叉搜索树中指定节点的 下一个 节点 也即中序后继 如果指定节点没有对应的 下一个 节点 则返回null 来源 力扣 LeetCode 链接 https leetcode cn problems successor
  • nextTick 原理及作用

    Vue 的 nextTick 其本质是对 JavaScript 执行原理 EventLoop 的一种应用 nextTick 的核心是利用了如 Promise MutationObserver setImmediate setTimeout的
  • Leetcode刷题-最长公共前缀

    Leetcode刷题 最长公共前缀 简介 题目 个人答案及结果 学习一下官方的 简介 最近尝试下大家口口相传的神器 leetcode cn com 大家自己注册就可以选择题库进行使用了 我都会先自己出一个答案 然后再学习别人的标准答案 进行
  • element修改el-table 表头的背景颜色横向渐变色 + 修改表头背景颜色

    vue element ui 修改el table 表头的背景颜色横向渐变色 修改表头背景颜色 表头背景颜色横向渐变效果图 修改表头背景颜色和字体颜色效果图 直接上代码 修改表头的背景颜色横向渐变色的代码 html
  • SSH一段时间未使用自动断开的解决办法

    有两种解决方案 可以修改服务器端的参数 也可以修改本地链接的参数 为了安全起见 我这里选择了修改我本地的配置 在路径 etc ssh ssh config下添加如下配置 ServerAliveInterval 60 ServerAliveC
  • HTML的Input(type)的属性都有哪些

    作者介绍 一个有梦想 有理想 有目标的 且渴望能够学有所成的追梦人 学习格言 不读书的人 思想就会停止 狄德罗 个人主页 进入博主主页 欢迎小伙伴们访问到博主的文章内容 在浏览阅读过程发现需要纠正的地方 烦请指出 愿能与诸君一同成长 目录
  • [ZZ]计算机视觉、机器学习相关领域论文和源代码大集合

    注 下面有project网站的大部分都有paper和相应的code Code一般是C C 或者Matlab代码 最近一次更新 2013 1 29 一 特征提取Feature Extraction SIFT 1 Demo program SI
  • [python logging]日志记录模块

    logging 介绍 Logger从来不直接实例化 经常通过logging模块级方法 Module Level Function logging getLogger name 来获得 其中如果name不给定就用root 名字是以点号分割的命