Python日志模块学习,从这里开始...

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 学习python的第一课,肯定都是 print('Hello Wrold...')。但print仅仅使用与我们日常学习,当我们的程序需要部署上线时,程序必须要具备记录日志与程序输出的功能。此时print就不能满足我们的需求,而logging应运而生。logging是python的内置模块,无需安装即可直接使用。logging模块借鉴了Apache的Log4j中很多的功能与特性,使用起来较为方便,不论你是最简单无脑输出还是定义自己的过滤器与格式,最终都能满足大家的需求,所以logging模块是你的必修课!

消息与记录


刚才谈到了关于历史账号的文章与消息记录,所以今天想跟大家聊聊Python关于消息记录的模块:日志管理模块 logging

学习python的第一课,肯定都是 print('Hello Wrold...')。但print仅仅使用与我们日常学习,当我们的程序需要部署上线时,程序必须要具备记录日志与程序输出的功能。此时print就不能满足我们的需求,而logging应运而生。

logging是python的内置模块,无需安装即可直接使用。logging模块借鉴了Apache的Log4j中很多的功能与特性,使用起来较为方便,不论你是最简单无脑输出还是定义自己的过滤器与格式,最终都能满足大家的需求,所以logging模块是你的必修课!


Logging入门



日志级别

不论是python、java还是C,日志的级别都是统一规定的:

日志级别 使用范围
FATAL 致命错误
CRITICAL 严重的错误,如内存耗尽、磁盘空间不足等.
ERROR 错误,如IO异常,文件读写异常等
WARNING 警告类错误,如用户输入密码即将过期提醒等
INFO 处理请求或者用户操作的状态及日常事务日志
DEBUG 调试过程中使用的日志等级,可用于后台问题定位

那么logging中存在哪些?默认分为六种日志级别(括号为级别对应的数值),NOTSET(0)、DEBUG(10)、INFO(20)、WARNING(30)、ERROR(40)、CRITICAL(50)。


简单日志打印

说了半天的日志级别,那么这东西对日志记录有什么用?此时我们需要了解LogLevel。logging模块默认记录日志的级别是大于等于WARNING。那么让我们来看第一个例子:

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

理想中我们期望的打印结果是从debug到critical,但现实是日志从warning级别开始打印。而且这种日志的打印和print又有什么区别,我们需要丰满日志的内容,提升逼格。


配置日志输出

logging提供了basicConfig函数,用于对日志输入进行相关配置。

让我们来看看basicConfig有哪些可配置参数吧:

filename: 指定日志文件名

filemode: 和file函数意义相同,指定日志文件的打开模式,'w'或'a'

format: 指定输出的格式和内容,format可以输出很多有用信息,如上例所示:

%(levelno)s: 打印日志级别的数值

%(levelname)s: 打印日志级别名称

%(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]

%(filename)s: 打印当前执行程序名

%(funcName)s: 打印日志的当前函数

%(lineno)d: 打印日志的当前行号

%(asctime)s: 打印日志的时间

%(thread)d: 打印线程ID

%(threadName)s: 打印线程名称

%(process)d: 打印进程ID

%(message)s: 打印日志信息

datefmt: 指定时间格式,同time.strftime()

level: 设置日志级别,默认为logging.WARNING

stream: 指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,

    默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略

import logging
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(message)s', datefmt='%Y-%m-%d')
logging.debug('This is debug message')
logging.info('This is info message')
logging.warning('This is warning message')
logging.error('This is error message')
logging.critical('This is critical message')
>>> 2019-09-01 23:56:33 LearnLogging.py[line:38] This is debug message
>>> 2019-09-01 23:56:33 LearnLogging.py[line:39] This is info message
>>> 2019-09-01 23:56:33 LearnLogging.py[line:40] This is warning message
>>> 2019-09-01 23:56:33 LearnLogging.py[line:41] This is error message
>>> 2019-09-01 23:56:33 LearnLogging.py[line:42] This is critical message

通过配置basicConfig,日志输出看起来就工整多了...当看到第一个filename的时候就想到了,现在的日志都是在控制台输出的,我们添加该参数后,就可以将日志输出到文本了,对吧?答案是肯定的,如下图:


网络异常,图片无法展示
|

日志保存文本


但此时出现一个问题,我们的日志都保存到了文本中,前台的控制栏不再具备日志输出功能了!这该如何是好?


Logging进阶


刚才提到的入门使用,只是针对logging的一个简单操作,如果我们想深入的去使用logging模块,就必须了解Logger,Handler,Formatter,Filter的概念:

  • Logger提供了应用程序可以直接使用的接口;
  • Handler将(logger创建的)日志记录发送到合适的目的输出;
  • Filters提供了细度设备来决定输出哪条日志记录;
  • Formatter决定日志记录的最终输出格式。

Logger

Logger 对象要做三件事情。首先,它们向应用代码暴露了许多方法,这样应用可以在运行时记录消息。其次,记录器对象通过严重程度(默认的过滤设施)或者过滤器对象来决定哪些日志消息需要记录下来。第三,记录器对象将相关的日志消息传递给所有感兴趣的日志处理器。

常用的记录器对象的方法分为两类:配置和发送消息。

这些是最常用的配置方法:

Logger.setLevel()指定logger将会处理的最低的安全等级日志信息, debug是最低的内置安全等级,critical是最高的内建安全等级。例如,如果严重程度为INFO,记录器将只处理INFO,WARNING,ERROR和CRITICAL消息,DEBUG消息被忽略。

Logger.addHandler()和Logger.removeHandler()从记录器对象中添加和删除处理程序对象。处理器详见Handlers。

Logger.addFilter()和Logger.removeFilter()从记录器对象添加和删除过滤器对象。


Handlers

处理程序对象负责将适当的日志消息(基于日志消息的严重性)分派到处理程序的指定目标。Logger 对象可以通过addHandler()方法增加零个或多个handler对象。举个例子,一个应用可以将所有的日志消息发送至日志文件,所有的错误级别(error)及以上的日志消息发送至标准输出,所有的严重级别(critical)日志消息发送至某个电子邮箱。在这个例子中需要三个独立的处理器,每一个负责将特定级别的消息发送至特定的位置。

其中常用的有4种:

  • logging.StreamHandler -> 控制台输出
  • logging.FileHandler  -> 文件输出
  • logging.handlers.RotatingFileHandler
  • logging.handlers.TimedRotatingFileHandler

Formatter

Formatter对象设置日志信息最后的规则、结构和内容,默认的时间格式为%Y-%m-%d %H:%M:%S,下面是Formatter常用的一些信息

参数 说明
%(name)s Logger的名字
%(levelno)s 数字形式的日志级别
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有
%(message)s 用户输出的消息

此时我们就可以实现日志的前后台输出了:

import logging
logger = logging.getLogger(__name__)
logger.setLevel(level=logging.INFO)
formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(message)s',
                              datefmt='%Y-%m-%d %H:%M:%S')
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
handler.setFormatter(formatter)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter)
logger.addHandler(handler)
logger.addHandler(console)
logger.debug('This is debug message')
logger.info('This is info message')
logger.warning('This is warning message')
logger.error('This is error message')
logger.critical('This is critical message')
>>> 2019-09-02 00:49:58 LearnLogging.py[line:62] This is info message
>>> 2019-09-02 00:49:58 LearnLogging.py[line:63] This is warning message
>>> 2019-09-02 00:49:58 LearnLogging.py[line:64] This is error message
>>> 2019-09-02 00:49:58 LearnLogging.py[line:65] This is critical message

此时,前后台均输出了相关的日志信息。


Logging特别操作



日志切片

有时候,系统后台的日志会输出的比较频繁,那么我们如何将日志按照大小或者时间进行切片呢?这里就要用到刚才介绍的:

  • logging.handlers.RotatingFileHandler
  • logging.handlers.TimedRotatingFileHandler

每隔 1000 Byte 划分一个日志文件,备份文件为 3 个

file_handler = logging.handlers.RotatingFileHandler("test.log", mode="w", maxBytes=1000, backupCount=3, encoding="utf-8")

每隔 1小时 划分一个日志文件,interval 是时间间隔,备份文件为 10 个

handler2 = logging.handlers.TimedRotatingFileHandler("test.log", when="H", interval=1, backupCount=10)

我们以RotatingFileHandler为例,为了演示方便,我设置文件大小为3kb:

import logging
from logging.handlers import RotatingFileHandler
logger = logging.getLogger(__name__)
logger.setLevel(level=logging.INFO)
formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(message)s',
                              datefmt='%Y-%m-%d %H:%M:%S')
handler = RotatingFileHandler("log.txt", maxBytes=1024*3, backupCount=3)
handler.setLevel(logging.INFO)
handler.setFormatter(formatter)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter)
logger.addHandler(handler)
logger.addHandler(console)
for i in range(10):
    logger.info(i)
    logger.debug('This is debug message')
    logger.info('This is info message')
    logger.warning('This is warning message')
    logger.error('This is error message')
    logger.critical('This is critical message')

最终实现:


网络异常,图片无法展示
|

日志记录


关于异常日志

logging模块在对异常获取时,进行了相关的优化操作,来看下这个例子:

import logging
logger = logging.getLogger(__name__)
logger.setLevel(level=logging.INFO)
formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(message)s',
                              datefmt='%Y-%m-%d %H:%M:%S')
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter)
logger.addHandler(console)
try:
    1/0
except Exception as error:
    logger.error(error)
    logger.error(error, exc_info=True)
    logger.exception(error)
>>> 2019-09-02 01:06:15 LearnLogging.py[line:87] division by zero
>>> 2019-09-02 01:06:15 LearnLogging.py[line:89] division by zero
    Traceback (most recent call last):
      File "D:/Codes_Repository/Python/PythonTests/37.Python日志模块/LearnLogging.py", line 85, in <module>
        1/0
    ZeroDivisionError: division by zero
>>> 2019-09-02 01:06:15 LearnLogging.py[line:91] division by zero
    Traceback (most recent call last):
      File "D:/Codes_Repository/Python/PythonTests/37.Python日志模块/LearnLogging.py", line 85, in <module>
        1/0
    ZeroDivisionError: division by zero

由此可见,当我们在对异常结果进行日志输出时,最好使用logger.exception。

其实logging模块的内容还有很多,比如封装与继承,今天就先介绍到这里,有空了继续为大家补充。


The End


OK,今天的内容就到这里




相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
2月前
|
SQL 关系型数据库 数据库
Python SQLAlchemy模块:从入门到实战的数据库操作指南
免费提供Python+PyCharm编程环境,结合SQLAlchemy ORM框架详解数据库开发。涵盖连接配置、模型定义、CRUD操作、事务控制及Alembic迁移工具,以电商订单系统为例,深入讲解高并发场景下的性能优化与最佳实践,助你高效构建数据驱动应用。
304 7
|
2月前
|
存储 Java 数据处理
(numpy)Python做数据处理必备框架!(一):认识numpy;从概念层面开始学习ndarray数组:形状、数组转置、数值范围、矩阵...
Numpy是什么? numpy是Python中科学计算的基础包。 它是一个Python库,提供多维数组对象、各种派生对象(例如掩码数组和矩阵)以及用于对数组进行快速操作的各种方法,包括数学、逻辑、形状操作、排序、选择、I/0 、离散傅里叶变换、基本线性代数、基本统计运算、随机模拟等等。 Numpy能做什么? numpy的部分功能如下: ndarray,一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组 用于对整组数据进行快速运算的标准数学函数(无需编写循环)。 用于读写磁盘数据的工具以及用于操作内存映射文件的工具。 线性代数、随机数生成以及傅里叶变换功能。 用于集成由C、C++
308 1
|
2月前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
170 1
|
2月前
|
算法 Java Docker
(Python基础)新时代语言!一起学习Python吧!(三):IF条件判断和match匹配;Python中的循环:for...in、while循环;循环操作关键字;Python函数使用方法
IF 条件判断 使用if语句,对条件进行判断 true则执行代码块缩进语句 false则不执行代码块缩进语句,如果有else 或 elif 则进入相应的规则中执行
266 1
|
2月前
|
监控 安全 程序员
Python日志模块配置:从print到logging的优雅升级指南
从 `print` 到 `logging` 是 Python 开发的必经之路。`print` 调试简单却难维护,日志混乱、无法分级、缺乏上下文;而 `logging` 支持级别控制、多输出、结构化记录,助力项目可维护性升级。本文详解痛点、优势、迁移方案与最佳实践,助你构建专业日志系统,让程序“有记忆”。
228 0
|
2月前
|
JSON 算法 API
Python中的json模块:从基础到进阶的实用指南
本文深入解析Python内置json模块的使用,涵盖序列化与反序列化核心函数、参数配置、中文处理、自定义对象转换及异常处理,并介绍性能优化与第三方库扩展,助你高效实现JSON数据交互。(238字)
356 4
|
2月前
|
存储 Java 索引
(Python基础)新时代语言!一起学习Python吧!(二):字符编码由来;Python字符串、字符串格式化;list集合和tuple元组区别
字符编码 我们要清楚,计算机最开始的表达都是由二进制而来 我们要想通过二进制来表示我们熟知的字符看看以下的变化 例如: 1 的二进制编码为 0000 0001 我们通过A这个字符,让其在计算机内部存储(现如今,A 字符在地址通常表示为65) 现在拿A举例: 在计算机内部 A字符,它本身表示为 65这个数,在计算机底层会转为二进制码 也意味着A字符在底层表示为 1000001 通过这样的字符表示进行转换,逐步发展为拥有127个字符的编码存储到计算机中,这个编码表也被称为ASCII编码。 但随时代变迁,ASCII编码逐渐暴露短板,全球有上百种语言,光是ASCII编码并不能够满足需求
157 4
|
2月前
|
Java 调度 数据库
Python threading模块:多线程编程的实战指南
本文深入讲解Python多线程编程,涵盖threading模块的核心用法:线程创建、生命周期、同步机制(锁、信号量、条件变量)、线程通信(队列)、守护线程与线程池应用。结合实战案例,如多线程下载器,帮助开发者提升程序并发性能,适用于I/O密集型任务处理。
263 0
|
2月前
|
XML JSON 数据处理
超越JSON:Python结构化数据处理模块全解析
本文深入解析Python中12个核心数据处理模块,涵盖csv、pandas、pickle、shelve、struct、configparser、xml、numpy、array、sqlite3和msgpack,覆盖表格处理、序列化、配置管理、科学计算等六大场景,结合真实案例与决策树,助你高效应对各类数据挑战。(238字)
178 0

推荐镜像

更多