相关链接

第一篇:日志基础与基本配置

在开发和维护应用程序的过程中,日志是一个非常重要的工具。它不仅可以帮助开发者了解程序的运行状态,还能帮助定位和解决问题。本文将详细介绍日志的概念、Python中 logging 模块的基本使用、日志级别以及如何配置日志格式和输出位置,并通过实际示例展示这些配置的效果。

日志的概念与用途

日志是一种用于记录程序运行过程中重要事件的工具。通过日志,开发者可以:

  • 了解程序的运行状态和进程。
  • 发现和定位程序中的错误和异常。
  • 分析和优化程序性能。
  • 记录系统或应用程序的使用情况和用户行为。

Python logging 模块介绍

Python 的 logging 模块是标准库的一部分,提供了灵活和强大的日志记录功能。它允许开发者将日志消息发送到多个目标,如控制台、文件、网络等。logging 模块支持不同的日志级别、格式化和处理器,使得日志记录更加方便和可控。

日志级别

日志级别用于指定日志消息的重要性。Python logging 模块定义了五个标准日志级别,每个级别都有对应的数值:

  • DEBUG (10): 详细的信息, 通常只在诊断问题时使用。
  • INFO (20): 确认程序按预期工作的信息。
  • WARNING (30): 表示某些非严重问题,警告可能会出现问题。
  • ERROR (40): 由于更严重的问题,程序已不能执行某些功能。
  • CRITICAL (50): 严重错误,表明程序可能无法继续运行。

配置日志格式和输出位置

logging 模块允许开发者配置日志格式和输出位置。日志格式定义了日志消息的显示方式,而输出位置定义了日志消息的存储位置(如控制台、文件等)。

配置日志格式

日志格式可以通过 format 参数进行设置,例如:

1
format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'  # 定义日志消息的格式

配置输出位置

输出位置可以通过设置处理器(Handler)来配置。例如,可以将日志消息输出到控制台或文件:

1
2
3
4
5
6
7
8
9
import logging

# 输出到控制台
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO) # 当日志级别等于或高于INFO时,会输出到控制台。

# 输出到文件
file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.WARNING) # 当日志级别等于或高于WARNING时,会输出到文件。

实验:基本日志配置和输出

在这一部分,我们将通过实际的代码示例来演示如何配置日志并查看输出结果。

实验1:基本日志配置

创建一个简单的 Python 脚本 basic_logging.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import logging
import os

# 获取当前脚本的目录
current_directory = os.path.dirname(os.path.abspath(__file__))

# 日志文件的完整路径
log_file_path = os.path.join(current_directory, 'app_1.log')


# 配置基本的日志设置
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[logging.StreamHandler(),
logging.FileHandler(log_file_path)])

logger = logging.getLogger(__name__)

# 记录不同级别的日志
logger.debug('这是一个DEBUG级别的日志')
logger.info('这是一个INFO级别的日志')
logger.warning('这是一个WARNING级别的日志')
logger.error('这是一个ERROR级别的日志')
logger.critical('这是一个CRITICAL级别的日志')

运行脚本后,你将看到以下输出: 控制台输出:

1
2
3
4
2024-07-25 07:50:36,800 - __main__ - INFO - 这是一个INFO级别的日志
2024-07-25 07:50:36,800 - __main__ - WARNING - 这是一个WARNING级别的日志
2024-07-25 07:50:36,801 - __main__ - ERROR - 这是一个ERROR级别的日志
2024-07-25 07:50:36,801 - __main__ - CRITICAL - 这是一个CRITICAL级别的日志

文件 app_1.log 输出:

1
2
3
4
5
2024-07-25 07:50:36,800 - __main__ - INFO - 这是一个INFO级别的日志
2024-07-25 07:50:36,800 - __main__ - WARNING - 这是一个WARNING级别的日志
2024-07-25 07:50:36,801 - __main__ - ERROR - 这是一个ERROR级别的日志
2024-07-25 07:50:36,801 - __main__ - CRITICAL - 这是一个CRITICAL级别的日志

在这个实验中,DEBUG 级别的日志不会输出到控制台和文件,因为StreamHandlerFileHandler 的日志等级没有单独设置,它们会默认继承根记录器(root logger)的日志等级,即 logging.basicConfig 中设置的等级INFO

实验2:使用配置文件配置日志

创建一个 YAML 配置文件 logging_config.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
version: 1  # 配置文件的版本

formatters: # 定义日志格式化器
simple: # 名为simple的格式化器
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s' # 日志消息的格式,包括时间、记录器名称、日志级别和消息内容

handlers: # 定义日志处理器
console: # 名为console的处理器,输出到控制台
class: logging.StreamHandler # 使用StreamHandler类
level: DEBUG # 处理器的日志级别为DEBUG
formatter: simple # 使用名为simple的格式化器
stream: ext://sys.stdout # 输出到标准输出,即控制台

file: # 名为file的处理器,输出到文件
class: logging.FileHandler # 使用FileHandler类
level: WARNING # 处理器的日志级别为WARNING
formatter: simple # 使用名为simple的格式化器
filename: path/to/app_2.log # log文件绝对路径

loggers: # 定义日志记录器
__main__: # 针对主模块的记录器
level: DEBUG # 记录器的日志级别为DEBUG
handlers: [console, file] # 使用console和file两个处理器
propagate: no # 不向更高层次的记录器传递日志消息

root: # 根记录器,适用于所有模块
level: DEBUG # 记录器的日志级别为DEBUG
handlers: [console, file] # 使用console和file两个处理器

创建一个 Python 脚本 logging_with_config.py 来加载这个配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import logging.config
import yaml
import os

# 获取当前脚本的目录
current_directory = os.path.dirname(os.path.abspath(__file__))

# 日志文件的完整路径
cfg_file_path = os.path.join(current_directory, './logging_config.yaml')

with open(cfg_file_path, 'r') as f:
config = yaml.safe_load(f.read())
logging.config.dictConfig(config)

logger = logging.getLogger(__name__)

# 记录不同级别的日志
logger.debug('这是一个DEBUG级别的日志')
logger.info('这是一个INFO级别的日志')
logger.warning('这是一个WARNING级别的日志')
logger.error('这是一个ERROR级别的日志')
logger.critical('这是一个CRITICAL级别的日志')

运行脚本后,你将看到以下输出:

控制台输出:

1
2
3
4
5
2024-07-25 08:04:02,433 - __main__ - DEBUG - 这是一个DEBUG级别的日志
2024-07-25 08:04:02,433 - __main__ - INFO - 这是一个INFO级别的日志
2024-07-25 08:04:02,433 - __main__ - WARNING - 这是一个WARNING级别的日志
2024-07-25 08:04:02,434 - __main__ - ERROR - 这是一个ERROR级别的日志
2024-07-25 08:04:02,434 - __main__ - CRITICAL - 这是一个CRITICAL级别的日志

文件 app_2.log 输出:

1
2
3
2024-07-25 08:04:02,433 - __main__ - WARNING - 这是一个WARNING级别的日志
2024-07-25 08:04:02,434 - __main__ - ERROR - 这是一个ERROR级别的日志
2024-07-25 08:04:02,434 - __main__ - CRITICAL - 这是一个CRITICAL级别的日志

console处理器的等级为INFO,而file处理器的等级为WARNING。所以控制台会输出所有信息,即等级等于或大于DEBUG的信息,但文件中只会记录等级等于或大于WARNING的记录。

文章总结

在本篇文章中,我们学习了Python logging 模块的基础内容,包括日志级别、基本配置以及如何将日志输出到控制台和文件。这为我们搭建了日志系统的基本框架,使我们能够了解程序的运行状态和关键事件。

接下来,我们将在第二篇文章中深入探讨更高级的配置内容,重点介绍日志处理器(Handlers)、日志格式器(Formatters)和日志过滤器(Filters)。我们将通过模拟实践,配置不同类型的处理器(如StreamHandlerFileHandlerRotatingFileHandler等),并自定义日志格式和过滤规则,从而更灵活地控制日志的输出目标、格式和内容。

通过这些高级配置,我们可以更好地满足不同应用场景下的日志需求,如限制日志文件大小、按时间轮转日志文件、以及只记录特定级别的日志信息。