简介

在所有项目中必不可少的一定是日志记录系统,python为我们提供了一个比较方便的日志模块logging,通常,我们都会基于此模块编写一个日志记录类,方便将项目中的日志记录到文件中。

logging

日志主要分为如下几个等级。

日志等级 描述
DEBUG 详细信息,通常仅在诊断问题时才有意义。
INFO 无异常时输出的日志,主要是确认程序是否正常按照预期进行的
WARNING 当出现一些异常信息(例如磁盘空间不足)时,但是不会影响程序的正常执行
ERROR 当出现问题时导致程序无法正常运行时
CRITICAL 当出现严重问题时导致程序无法继续运行时
import logging

logging.info("info")
logging.warning("warning")
logging.debug("debug")
logging.error("error")
logging.critical("critical")
WARNING:root:warning
ERROR:root:error
CRITICAL:root:critical

由此可见,info,debug信息未输出,是因为默认的level等级是warning。

logging模块中的四个基本类和对应功能

名称 功能
Loggers 公开应用程序代码直接使用的接口。
Handlers 将日志记录(由记录器创建)发送到适当的目的地(标准输出、文件等)。
Filters 提供了更细粒度的工具来确定要输出哪些日志记录。
Formatters 指定最终输出中日志记录的布局。

日志输出到文件

使用basicConfig进行配置

logging.basicConfig(filename="test.log", level=logging.INFO)
logging.info("info")
logging.warning("warning")
logging.debug("debug")
logging.error("error")
logging.critical("critical")
INFO:root:info
WARNING:root:warning
ERROR:root:error
CRITICAL:root:critical

由上述日志可得出:日志的组成

日志等级:日志记录器名称:日志内容

那么如何修改记录器名称?

通过如下方式可以实现记录器名称的修改

logger = logging.getLogger("test")
logging.basicConfig(filename="test.log", level=logging.INFO)
logger.info("info")
logger.warning("warning")
logger.debug("debug")
logger.error("error")
logger.critical("critical")
INFO:test:info
WARNING:test:warning
ERROR:test:error
CRITICAL:test:critical

由上述可见,虽然修改了记录器的名称,但格式还是不那么容易读懂的,因此需要修改一下日志的格式

如何修改日志输出的格式呢?

通过basicConfig中的format来修改

asctime:当前时间,levelname:等级名称,message:日志信息

logger = logging.getLogger("test")
logging.basicConfig(
filename="test.log",
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
)
logger.info("info")
logger.warning("warning")
logger.debug("debug")
logger.error("error")
logger.critical("critical")

Handler

处理器对象:将适当的日志消息(基于日志消息的严重性)分派到处理程序的指定目的地。 Logger 对象可以使用 addHandler() 方法向自己添加零个或多个处理程序对象。作为示例场景,应用程序可能希望将所有日志消息发送到日志文件,将所有错误或更高级别的日志消息发送到标准输出,并将所有关键消息发送到电子邮件地址。此方案需要三个单独的处理程序,其中每个处理程序负责将特定严重性的消息发送到特定位置。

handler主要有以下几种,此处列举出常用的几种。

名称 作用
StreamHandler 用于将日志记录直接在终端中输出
FileHandler 用于将日志记录输出到磁盘中
NullHandler 用于对日志记录不做任何输出
RotatingFileHandler 用于达到一定大小时,自动生成新的日志文件, 只适用于Linux
TimedRotatingFileHandler 用于对每天的日志文件进行输出, 只适用于Linux

Formatters

格式化对象:将日志转换成text并按照指定格式格式化输出日志字符串的格式。

常用的参数:fmt=None, datefmt=None

fmt:日志的展示格式,例如:

# 代表时间 日志等级 日志信息
%(asctime)s %(levelname)s %(message)s

主要有以下显示格式

%(name)s 记录器的名称(记录通道)
%(levelno)s 消息的数字日志级别(DEBUG、INFO、WARNING、ERROR、CRITICAL)
%(levelname)s 消息的文本记录级别 ("DEBUG", "INFO", WARNING、ERROR、CRITICAL)
%(pathname)s 记录日志的源文件的完整路径名已发出呼叫(如果可用)
%(filename)s 路径名的文件名部分
%(module)s 模块(文件名的名称部分)
%(lineno)d 发出记录调用的源行号(如果可供使用的话)
%(funcName)s 函数名
%(created)f 创建日志记录的时间 (time.time()返回值)
%(asctime)s 创建 LogRecord 的文本时间
%(msecs)d 创建时间的毫秒部分
%(relativeCreated)d 创建 LogRecord 的时间(以毫秒为单位),相对于加载日志模块的时间(通常在应用程序启动时)
%(thread)d 线程 ID(如果可用)
%(threadName)s 线程名称(如果可用)
%(process)d 进程 ID(如果可用)
%(message)s record.getMessage() 的结果,计算方式为 记录发出

datefmt:日志信息的时间格式,例如:

%Y-%m-%d %H:%M:%S

简单的日志记录类

import logging

def log():
# 创建一个日志对象
log = logging.getLogger("test")
# 设置记录器发给处理器handler的最低等级
log.setLevel(logging.DEBUG) # 创建一个处理器用于设置日志对象
handler = logging.StreamHandler()
# 设置handler发送给目标的最低等级
handler.setLevel(logging.DEBUG) # 创建格式器,设置输出日志格式
format = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(format) log.addHandler(handler) return log test_log: logging.Logger = log()
test_log.info("info")
test_log.debug("debug")
test_log.error("error")
test_log.critical("critical")
2022-07-12 17:19:23,396 - test - INFO - info
2022-07-12 17:19:23,396 - test - DEBUG - debug
2022-07-12 17:19:23,396 - test - ERROR - error
2022-07-12 17:19:23,396 - test - CRITICAL - critical

从配置文件中读取配置进行输出日志

import logging
import logging.config logging.config.fileConfig('logging.conf') logger = logging.getLogger('simpleExample') logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')

logging.conf

[loggers]
keys=root,simpleExample [handlers]
keys=consoleHandler [formatters]
keys=simpleFormatter [logger_root]
level=DEBUG
handlers=consoleHandler [logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0 [handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,) [formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
2022-07-12 17:22:55,953 - simpleExample - DEBUG - debug message
2022-07-12 17:22:55,953 - simpleExample - INFO - info message
2022-07-12 17:22:55,953 - simpleExample - WARNING - warn message
2022-07-12 17:22:55,953 - simpleExample - ERROR - error message
2022-07-12 17:22:55,953 - simpleExample - CRITICAL - critical message

通过配置文件方式进行日志格式的处理与上述类似。

日志记录类

下面的日志记录类,可以方便在项目中进行直接使用或者简单修改一下使用。

类方式实现

import logging
import pathlib class Log:
def __init__(self, file_name, logger_name=None):
self.file_name = file_name
self.logger = logging.getLogger(logger_name)
self.logger.setLevel(logging.DEBUG)
self.get_log() def get_log(self):
# FileHandler: 将格式化的日志记录写入磁盘文件的处理程序类
# 将格式化的日志记录写入磁盘文件的处理程序
handler = logging.FileHandler(self.file_name)
handler.setLevel(logging.DEBUG)
formater = logging.Formatter(
"%(asctime)s:%(filename)s:%(lineno)d:%(name)s:%(levelname)s:%(message)s"
)
handler.setFormatter(formater)
self.logger.addHandler(handler) def info(self, msg):
self.logger.info(msg) def debug(self, msg):
self.logger.debug(msg) def warning(self, msg):
self.logger.warning(msg) def error(self, msg):
self.logger.error(msg) def critical(self, msg):
self.logger.critical(msg) log_path = pathlib.Path(__file__).parent.joinpath("test.log") log = Log(log_path)
log.info("info")
2022-07-12 17:51:14,069:logger.py:24:root:INFO:info

目前发现日志的对应行数是类中的行数,使用函数方式则不会出现此问题

函数方式

def Log2(file_name, logger_name=None):
logger = logging.getLogger(logger_name)
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(file_name)
handler.setLevel(logging.DEBUG)
formater = logging.Formatter(
"%(asctime)s:%(filename)s:%(lineno)d:%(name)s:%(levelname)s:%(message)s"
)
handler.setFormatter(formater)
logger.addHandler(handler)
return logger log = Log2(log_path)
log.info("info")
2022-07-12 17:53:40,661:logger.py:59:root:INFO:info

参考

logging官方文档

python 日志类的更多相关文章

  1. python 日志的配置,python对日志封装成类,日志的调用

    # python 日志的配置,python对日志封装成类,日志的调用 import logging # 使用logging模块: class CLog: # --------------------- ...

  2. 简单实用的日志类CLog (Python版)

    #coding: utf-8 import time ''' /***************************************************************** Fu ...

  3. python日志模块

    许多应用程序中都会有日志模块,用于记录系统在运行过程中的一些关键信息,以便于对系 统的运行状况进行跟踪.在.NET平台中,有非常著名的第三方开源日志组件log4net,c++中,有人们熟悉的log4c ...

  4. Python日志输出——logging模块

    Python日志输出——logging模块 标签: loggingpythonimportmodulelog4j 2012-03-06 00:18 31605人阅读 评论(8) 收藏 举报 分类: P ...

  5. Python3自定义日志类教程

    一.说明 Python3的logging功能是比较丰富的支持不同层次的日志输出,但或是我们想在日志前输出时间.或是我们想要将日志输入到文件,我们还是想要自定义日志类. 之前自己也尝试写过但感觉文档太乱 ...

  6. Python 日志输出中添加上下文信息

    Python日志输出中添加上下文信息 除了传递给日志记录函数的参数(如msg)外,有时候我们还想在日志输出中包含一些额外的上下文信息.比如,在一个网络应用中,可能希望在日志中记录客户端的特定信息,如: ...

  7. 孤荷凌寒自学python第二十一天初识python的类

    孤荷凌寒自学python第二十一天初识python的类 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 类是面向对象的编程语言非常重要的概念. 编程语言的进化史中从顺序编程到结构化编程,最后才 ...

  8. Python - 关于类(self/cls) 以及 多进程通讯的思考

    Python-多进程中关于类以及类实例的一些思考 目录 Python-多进程中关于类以及类实例的一些思考 1. 背景 2. Python 类中的函数 - staticmethod / classmet ...

  9. [C#] 日志类

    在程序发布到服务器上的时候,不能在像本地执行一样可以调试,在发生错误时候,往往不能很方便的查找错误.将错误信息写入文件是一种比较常用的处理方法.以下是一个日志类,实现以下功能: 1)按日期每天生产不同 ...

随机推荐

  1. 隐藏浏览器header中X-Powered-By: PHP信息

    在php程序中,默认会在http请求响应头中输出php版本信息.如下: HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Date: Tue ...

  2. 一个关于 useState 的误解

    一个关于 useState 的误解 本文写于 2020 年 11 月 17 日 前两天有人问了我一个问题,他有一段这样的代码: function App() { const [n, setN] = u ...

  3. 拯救一切强迫症 - 读《编写可维护的 JavaScript》(一)

    拯救一切强迫症 - 读<编写可维护的 JavaScript>(一) 本文写于 2020 年 4 月 24 日 我在小学的时候就有接触过编程,所以读大一的时候 C 语言还算是轻车熟路.自然会 ...

  4. JWT 访问令牌

    JWT 访问令牌 更为详细的介绍jwt 在学习jwt之前我们首先了解一下用户身份验证 1 单一服务器认证模式 一般过程如下: 用户向服务器发送用户名和密码. 验证服务器后,相关数据(如用户名,用户角色 ...

  5. 561. Array Partition I - LeetCode

    Question 561. Array Partition I Solution 题目大意是,给的数组大小是2n,把数组分成n组,每组2个元素,每个组取最小值,这样就能得到n个值,怎样分组才能使这n个 ...

  6. linux篇-linux 下建立多个tomcat

    第一步:复制,解压 将准备好的tomcat压缩包复制到你准备安装的目录,我的tomcat压缩包名字是tomcat.tar.gz,我的安 装目录是 /usr/java/tomcat 第二步:解压tomc ...

  7. 好客租房14-在jsx中使用javascript表达式的注意点

    注意点 单大括号中可以使用任意的表达式 jsx自身也是js表达式 注意:js中的对是一个例外 写在style样式中 //导入react     import React from "reac ...

  8. python之部分内置函数与迭代器与异常处理

    目录 常见内置函数(部分) 可迭代对象 迭代器对象 for循环内部原理 异常处理 异常信息的组成部分 异常的分类 异常处理实操 异常处理的其他操作 for循环本质 迭代取值与索引取值的区别 常见内置函 ...

  9. 编程语言与python与pycharm的下载

    目录 编程语言的发展史 编程语言的分类 python解释器 python解释器的下载与安装 环境变量 执行python程序方式 pycharm编辑器 编程语言的发展史 机器语言是最开始的编程语言,之后 ...

  10. 对TCP粘包拆包的理解

    TCP的粘包与拆包 TCP是一种字节流(byte-stream)协议,所谓流,就是没有界限的一串数据. 一个完整的包会被TCP拆为多个包进行发送,也有可能把多个小包封装成一个大的数据包发送,这就是所谓 ...