【Python日志模块全面指南】:记录每一行代码的呼吸,掌握应用程序的脉搏

文章目录

🚀一、了解日志

日志是记录了一系列事件或活动的文件。在计算机领域,它通常用于记录程序或系统的运行状况和维护信息,以便在需要时进行故障排除或回溯。通过分析日志文件,管理员可以了解系统的使用情况、问题发生的原因以及如何解决这些问题。

日志通常包含时间戳、事件描述、错误消息、警报等信息。它们可以按照不同的标准来分类和过滤,例如按照事件类型、日志级别、时间戳范围等。常见的日志类型包括系统日志、安全日志、应用程序日志等。

🌈二、日志作用

  1. 调试和故障排除:通过分析日志文件可以了解系统崩溃或出现异常的原因,进而进行修复和调试。
  2. 性能调优:通过记录系统性能指标和资源利用情况等信息,管理员可以了解系统的瓶颈所在,从而进行针对性的优化。
  3. 安全审计:日志可以记录系统的安全事件、访问控制和行为审计等信息,以便于发现并防止潜在的安全问题。
  4. 统计分析:管理员可以通过日志记录用户行为、系统使用情况、网络流量等信息进行统计分析,以便于优化服务和提高用户满意度。

🌈三、了解日志模块

logging 模块提供了一种灵活且易于使用的方式来记录应用程序的状态和调试信息。它允许将消息分发到多个处理程序(handlers),并支持不同级别的日志消息。

logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;

⭐四、日志级别

在 logging 模块中,日志级别用于描述日志的重要程度。它们按照严重程度分为以下五个级别:
    DEBUG:最详细的日志信息,通常只在调试问题时使用;
    INFO:确认一切按预期运行;
    WARNING:表示发生了一些意外或异常情况,但是该软件还可以正常运行;
    ERROR:由于更严重的问题,软件已无法执行某些功能;
    CRITICAL:严重错误,表明程序本身可能无法继续运行。

默认情况下,logging 组件会关闭低级别的日志消息并仅记录 WARNING 级别及其以上的消息。如果需要记录更多详细信息,则需要将 Logger 的 level 属性设置为其他级别。

python 复制代码
# DEBUG
# 最详细的调试信息,通常只在开发阶段使用。通过记录变量值、函数参数、分支走向等信息帮助调试人员解决问题。
python 复制代码
# INFO
# INFO 级别的日志通常用于确认系统正在按预期运行。例如,记录请求的处理时间、数据库操作数量、任务的完成状态等。
python 复制代码
# WARNING
# WARNING 级别的日志表示出现了一些意外或异常情况,但是该软件还可以正常运行。例如,数据缺失或配置文件格式错误等。
python 复制代码
# ERROR
# ERROR 级别的日志表示由于更严重的问题,软件已无法执行某些功能。例如,数据库连接失败、文件无法打开等错误。
python 复制代码
# CRITICAL
# 最高级别的日志级别,用于记录严重错误,表明程序本身可能无法继续运行。例如,内存耗尽、服务器崩溃等。

在应用程序中,通常会使用多个不同的日志级别来记录不同类型的事件。这使得开发人员可以快速识别和排除问题,并加快故障排除的过程。

python 复制代码
# 开发应用程序或部署开发环境时,
# 可以使用DEBUG或INFO级别的日志获取尽可能详细的日志信息来进行开发或部署调试;
# 
# 
# 
# 应用上线或部署生产环境时,应该使用WARNING或ERROR或CRITICAL级别的日志来降低机器的I/O压力和提高获取错误日志信息的效率。
# 日志级别的指定通常都是在应用程序的配置文件中进行指定的。
# 
# 
# 
# 说明:
# 
# -上面列表中的日志等级是从上到下依次升高的,
#     即:DEBUG < INFO < WARNING < ERROR < CRITICAL,
#     而日志的信息量是依次减少的;
# 
# -当为某个应用程序指定一个日志级别后,
#     应用程序会记录所有日志级别大于或等于指定日志级别的日志信息,
#     而不是仅仅记录指定级别的日志信息,
#     nginx、php等应用程序以及这里的python的logging模块都是这样的。
#     同样,logging模块也可以指定日志记录器的日志级别,
#     只有级别大于或等于该指定日志级别的日志记录才会被输出,小于该等级的日志记录将会被丢弃。

💥五、记录日志-基础

logging.getLogger(name=None) 是 logging 模块中的一个重要函数,用于创建并返回一个 logger 对象。这个函数可以接受一个字符串作为参数,该字符串表示要创建的 logger 的名称。如果未提供名称,则会创建一个名为 root 的默认 logger。

python 复制代码
import logging

# 创建一个 logger
logger = logging.getLogger('my_logger')
logger.setLevel(logging.INFO)


# 将 StreamHandler 添加到 logger 中 --- StreamHandler处理器:将日志消息输出到标准输出或标准错误流。
logger.addHandler(logging.StreamHandler())

# 记录一条日志消息
logger.info('This is an info message')

logging 模块定义了五个日志级别(从低到高):DEBUG、INFO、WARNING、ERROR 和 CRITICAL。默认情况下,只有 WARNING 以及更高级别的日志消息才会被记录。可以通过设置 Logger 的日志级别来控制哪些消息应该被记录。

python 复制代码
logger.setLevel(logging.DEBUG) # 记录所有级别的日志消息
python 复制代码
import logging
 
# 创建一个 logger
logger = logging.getLogger('my_logger')
 
# 设置日志级别
logger.setLevel(logging.DEBUG)

# 将 StreamHandler 添加到 logger 中 --- StreamHandler处理器:将日志消息输出到标准输出或标准错误流。
logger.addHandler(logging.StreamHandler())
 
# 发布日志消息
logger.debug('This is a debug message')

# 创建了一个名为 'my_logger' 的 logger,设置其日志级别为 DEBUG,并发布了一条 DEBUG 级别的日志消息。

logging模块定义的模块级别的常用函数

函数 说明
logging.debug(msg, *args, **kwargs) 创建一条严重级别为DEBUG的日志记录
logging.info(msg, *args, **kwargs) 创建一条严重级别为INFO的日志记录
logging.warning(msg, *args, **kwargs) 创建一条严重级别为WARNING的日志记录
logging.error(msg, *args, **kwargs) 创建一条严重级别为ERROR的日志记录
logging.critical(msg, *args, **kwargs) 创建一条严重级别为CRITICAL的日志记录
logging.log(level, *args, **kwargs) 创建一条严重级别为level的日志记录
logging.basicConfig(**kwargs) 对root logger进行一次性配置
python 复制代码
 """
    logging.log() 函数的参数说明:
		level:指定要记录的日志级别,可选的取值有 DEBUG、INFO、WARNING、ERROR、CRITICAL。
		*args:需要记录的一个或多个日志消息(字符串)。
		**kwargs:可选参数,包括 extra、exc_info、stack_info、etc.
"""		
import logging
# 创建一个 logger
logger = logging.getLogger('my_logger')
# 设置日志级别
logger.setLevel(logging.DEBUG)
# 将 StreamHandler 添加到 logger 中 --- StreamHandler处理器:将日志消息输出到标准输出或标准错误流。
# logger.addHandler(logging.StreamHandler())
# 将一条消息记录到日志文件或控制台
logging.log(logging.INFO, 'This is an info message')

❤️六、记录日志-处理器handler

在 logging 模块中,处理器(handler)是一种组件,可以将日志记录到不同的位置,例如输出到文件、发送到电子邮件、发布至网络等等。每个 logger 可以拥有零个或多个 handler,用于控制将记录哪些消息到哪个位置。

logging 模块支持多种类型的处理器

python 复制代码
# StreamHandler:将日志消息输出到标准输出或标准错误流。
# 
# FileHandler:将日志消息输出到指定的文件中。
# 
# RotatingFileHandler:类似于 FileHandler,但它可以自动轮换多个日志文件,以避免一个文件太大而无法存储问题。
# 
# SMTPHandler:向指定的邮件地址发送日志消息。
# 
# SysLogHandler:向系统日志服务(syslog)输出日志消息。
# 
# NTEventLogHandler:向 Windows 事件日志输出日志消息。
python 复制代码
import logging
 
# 创建一个 logger
logger = logging.getLogger('my_logger')
logger.setLevel(logging.INFO)
 
# 创建一个 StreamHandler 并设置日志级别为 INFO
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
 
# 将 StreamHandler 添加到 logger 中
logger.addHandler(console_handler)
 
# 记录一条日志消息
logger.info('This is an info message')

# 首先创建了名为 'my_logger' 的 logger 对象,将其日志级别设置为 INFO。
# 然后,创建了一个名为 console_handler 的 StreamHandler 并将它的日志级别设置为 INFO。
# 最后,将 handler 添加到 logger 中,并通过 logger.info() 方法发布一条 INFO 级别的日志消息。

使用处理器 handler 可以扩展 logging 模块的功能并将日志记录到不同的位置,这对于应用程序的运行时跟踪或调试非常有用。

🎬七、记录日志-格式化记录

在 logging 模块中,格式化记录(Formatted log record)是一种将日志消息格式化为字符串的方式,以便于输出和阅读。可以使用 Formatter 类来创建自定义的格式化记录,以满足特定应用程序需求。

logging模块中定义好的可以用于format格式字符串说明

字段/属性名称 使用格式 描述
asctime %(asctime)s 将日志的时间构造成可读的形式,默认情况下是'2016-02-08 12:00:00,123'精确到毫秒
name %(name)s 所使用的日志器名称,默认是'root',因为默认使用的是 rootLogger
filename %(filename)s 调用日志输出函数的模块的文件名; pathname的文件名部分,包含文件后缀
funcName %(funcName)s 由哪个function发出的log, 调用日志输出函数的函数名
levelname %(levelname)s 日志的最终等级(被filter修改后的)
message %(message)s 日志信息, 日志记录的文本内容
lineno %(lineno)d 当前日志的行号, 调用日志输出函数的语句所在的代码行
levelno %(levelno)s 该日志记录的数字形式的日志级别(10, 20, 30, 40, 50)
pathname %(pathname)s 完整路径 ,调用日志输出函数的模块的完整路径名,可能没有
process %(process)s 当前进程, 进程ID。可能没有
processName %(processName)s 进程名称,Python 3.1新增
thread %(thread)s 当前线程, 线程ID。可能没有
threadName %(thread)s 线程名称
module %(module)s 调用日志输出函数的模块名, filename的名称部分,不包含后缀即不包含文件后缀的文件名
created %(created)f 当前时间,用UNIX标准的表示时间的浮点数表示; 日志事件发生的时间--时间戳,就是当时调用time.time()函数返回的值
relativeCreated %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数; 日志事件发生的时间相对于logging模块加载时间的相对毫秒数
msecs %(msecs)d 日志事件发生事件的毫秒部分。logging.basicConfig()中用了参数datefmt,将会去掉asctime中产生的毫秒部分,可以用这个加上
python 复制代码
import logging

# 创建一个 logger 对象,并设置其日志级别为 INFO
logger = logging.getLogger('my_logger')
logger.setLevel(logging.INFO)

# 创建一个 FileHandler,将日志记录到文件 'example.log' 中
fh = logging.FileHandler('example.log')

# 将 FileHandler 添加到 logger 中
logger.addHandler(fh)

# 创建一个 Formatter 对象并设置日志消息的格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)

# 记录一条 INFO 级别的日志消息
logger.info('This is an info message')

# 创建了名为 'my_logger' 的 logger 对象,并将其日志级别设为 INFO。接着,创建了一个 FileHandler 对象并将其添加到 logger 对象中。然后,通过 Formatter 类创建了一个格式化记录对象 formatter,并将其设置为日志消息的格式。最后,将 formatter 对象添加到 FileHandler 对象中,以便对每条日志消息进行格式化处理。

# 当调用 logger.info() 方法写入日志消息时,该消息会被传递给已经设置了格式化记录的 FileHandler 对象并格式化为指定的字符串格式。例如,如果设置了 '%(asctime)s - %(name)s - %(levelname)s - %(message)s' 的格式化字符串,则会在每条日志消息中输出时间戳、logger 对象的名称、日志级别和消息内容。
python 复制代码
import logging

# 创建一个 logger 对象,并设置其日志级别为 INFO
logger = logging.getLogger('my_logger')
logger.setLevel(logging.INFO)

# 创建一个 FileHandler,用于将日志记录到文件 'example.log' 中
fh = logging.FileHandler('example.log')

# 设置 FileHandler 的日志级别为 DEBUG
fh.setLevel(logging.DEBUG)

# 创建一个 Formatter 对象,用于设置日志消息的格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# 将 Formatter 对象添加到 FileHandler 中
fh.setFormatter(formatter)

# 将 FileHandler 添加到 logger 对象中
logger.addHandler(fh)

# 记录一条 INFO 级别的日志消息
logger.info('This is an info message')

# 记录一条 DEBUG 级别的日志消息
logger.debug('This is a debug message')

# 首先创建了名为 'my_logger' 的 logger 对象,并设置其日志级别为 INFO。接着,创建了一个 FileHandler 对象,并指定要将日志记录到文件 'example.log' 中。然后,将 FileHandler 的日志级别设置为 DEBUG,并创建一个 Formatter 对象,以控制日志消息的格式。最后,将 Formatter 对象和 FileHandler 对象添加到 logger 中。

# 在 logger 对象准备就绪后,可以通过调用 logger.info() 和 logger.debug() 方法发布不同级别的日志消息。这些消息将分别记录在 'example.log' 文件中,其中 INFO 级别的消息包含时间戳、logger 名称、日志级别和消息内容等信息,而 DEBUG 级别的消息则包含更多的细节信息,例如变量值和程序状态等。

格式化记录提供了一种控制和定制日志消息输出格式的方法,使其更容易阅读和理解。通过使用 Formatter 类,可以创建自定义的格式化记录并将其添加到 logger 对象中,以实现更灵活和有用的日志记录方案。

☔八、记录日志-配置logger

在 logging 模块中,可以使用 basicConfig() 函数或者通过编程的方式来配置 logger 对象的属性和行为。

通常情况下,在应用程序开始执行时调用 basicConfig() 函数即可完成全局的基本配置。

logging.basicConfig参数字段

参数名称 描述
filename 指定日志输出目标文件的文件名(可以写文件名也可以写文件的完整的绝对路径,写文件名日志放执行文件目录下,写完整路径按照完整路径生成日志文件),指定该设置项后日志信息就不会被输出到控制台了
filemode 指定日志文件的打开模式,默认为'a'。需要注意的是,该选项要在filename指定时才有效
format 指定日志格式字符串,即指定日志输出时所包含的字段信息以及它们的顺序。logging模块定义的格式字段下面会列出。
datefmt 指定日期/时间格式。需要注意的是,该选项要在format中包含时间字段%(asctime)s时才有效
level 指定日志器的日志级别
stream 指定日志输出目标stream,如sys.stdout、sys.stderr以及网络stream。需要说明的是,stream和filename不能同时提供,否则会引发 ValueError异常
style Python 3.2中新添加的配置项。指定format格式字符串的风格,可取值为'%'、'{'和'$',默认为'%'
handlers Python 3.3中新添加的配置项。该选项如果被指定,它应该是一个创建了多个Handler的可迭代对象,这些handler将会被添加到root logger。需要说明的是:filename、stream和handlers这三个配置项只能有一个存在,不能同时出现2个或3个,否则会引发ValueError异常。
%Y 四位数的年份表示(000-9999)
%y 两位数的年份表示(00-99)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00-59)
%S 秒(00-59)
%p 上午AM 下午 PM
python 复制代码
import logging
 
logging.basicConfig(filename='example.log', level=logging.DEBUG,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    datefmt='%m/%d/%Y %I:%M:%S %p')
 
# 记录一条日志消息
logging.info('This is an info message')

# 首先调用了 basicConfig() 函数,并传递了一些参数来设置日志记录器的属性。例如,指定了要将日志消息记录到文件 'example.log' 中,设置了默认日志级别为 DEBUG,指定了日期时间格式,以及设置了一个自定义的日志消息格式。
# 之后可以通过标准的日志记录函数(如 logging.info())来记录日志消息,这些函数都将根据 global basicConfig() 配置的内容记录日志。
需要注意的是,如果在多个模块或文件中使用相同的 logger 对象,则必须确保在所有地方都调用了 basicConfig() 函数,或者手动对所有 logger 对象进行配置。否则,可能会出现不同部分记录的日志信息不一致的问题。

总之,无论是使用 basicConfig() 函数还是编程方式来配置 logger 对象,都需要了解每个参数的含义和作用,并根据具体应用场景去设置它们。这些参数包括日志文件名、日志级别、日期时间格式、日志消息格式等方面。
python 复制代码
import logging
 
# 配置全局日志记录器属性
logging.basicConfig(filename='example.log', level=logging.DEBUG,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    datefmt='%m/%d/%Y %I:%M:%S %p')
 
# 创建一个 logger 对象
logger = logging.getLogger('my_logger')
logger.setLevel(logging.DEBUG)
 
# 给 logger 添加处理程序 ConsoleHandler,将日志消息输出到控制台
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
logger.addHandler(ch)
 
# 记录不同级别的日志消息
logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger.critical('This is a critical message')

👊九、流程梳理

python 复制代码
# 1、创建一个logger

# 2、设置下logger的日志的等级

# 3、创建合适的Handler(FileHandler要有路径)

# 4、设置下每个Handler的日志等级

# 5、创建下日志的格式

# 6、向Handler中添加上面创建的格式

# 7、将上面创建的Handler添加到logger中

# 8、打印输出logger.debug\logger.info\logger.warning\logger.error\logger.critical
python 复制代码
import logging

# 配置全局日志记录器属性
#logging.basicConfig(filename='example.log', level=logging.DEBUG,format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',datefmt='%m/%d/%Y %I:%M:%S %p')

# 创建logger,如果参数为空则返回root logger
logger = logging.getLogger("nick")
logger.setLevel(logging.DEBUG)  # 设置logger日志等级

# 创建handler
fh = logging.FileHandler("example.log", encoding="utf-8")
ch = logging.StreamHandler()

# 设置输出日志格式
formatter = logging.Formatter(
    fmt="%(asctime)s %(name)s %(filename)s %(message)s",
    datefmt="%Y/%m/%d %X"
)

# 注意 logging.Formatter的大小写

# 为handler指定输出格式,注意大小写
fh.setFormatter(formatter)
ch.setFormatter(formatter)

# 为logger添加的日志处理器
logger.addHandler(fh)
logger.addHandler(ch)

# 输出不同级别的log
logger.warning("警告")
logger.info("提示")
logger.error("错误")
相关推荐
枫の准大一7 分钟前
C++从零到满绩——类和对象(中)
开发语言·c++
HEX9CF12 分钟前
【数字图像处理+MATLAB】通过 Roberts, Prewitt, Sobel, LoG 等算子实现图像边缘检测:使用 edge 函数
开发语言·matlab·edge
研一计算机小白一枚13 分钟前
Which Tasks Should Be Learned Together in Multi-task Learning? 译文
人工智能·python·学习·机器学习
白云如幻17 分钟前
MySQL子查询介绍和where后的标量子查询
数据库·mysql
小玉起起22 分钟前
Redis Key 命名规范文档
数据库·redis·缓存
凡人的AI工具箱24 分钟前
40分钟学 Go 语言高并发实战:高性能缓存组件开发
开发语言·后端·缓存·架构·golang
大白的编程日记.27 分钟前
【C++笔记】数据结构进阶之二叉搜索树(BSTree)
开发语言·数据结构·c++·笔记
Eric.Lee202128 分钟前
数据集-目标检测系列- 蘑菇 检测数据集 mushroom >> DataBall
人工智能·python·yolo·目标检测·计算机视觉·蘑菇检测
每天一个秃顶小技巧29 分钟前
01.Golang 源码目录结构
开发语言·后端·golang
小柯J桑_29 分钟前
C++:用红黑树封装map与set-1
开发语言·c++·set·map·红黑树