logging 介绍
日志是对软件执行时所发生事件的一种追踪方式。软件开发人员对他们的代码添加日志调用,借此来指示某事件的发生。
什么时候使用日志
你可以通过执行 logger = getLogger(__name__)
创建一个日志记录器然后调用日志记录器的 debug()
, info()
, warning()
, error()
和 critical()
方法来使用日志记录功能。 要确定何时使用日志记录,以及确定要使用哪个日志记录器方法,请参阅下表。 它针对一组常见任务中的每一个都列出了最适合该任务的工具。
你想要执行的任务 |
此任务最好的工具 |
对于命令行或程序的应用,结果显示在控制台。 |
print() |
在对程序的普通操作发生时提交事件报告(比如:状态监控和错误调查) |
日志记录器的 info() (或者对于诊断目的需要非常详细的输出时则使用 debug() 方法) |
提出一个警告信息基于一个特殊的运行时事件 |
warnings.warn() 位于代码库中,该事件是可以避免的,需要修改客户端应用以消除告警 对于客户端应用无法干预,但事件仍然需要被关注的场合则使用日志记录器的 warning() 方法 |
对一个特殊的运行时事件报告错误 |
引发异常 |
报告错误而不引发异常(如在长时间运行中的服务端进程的错误处理) |
日志记录器的 error(), exception() 或 critical() 方法分别适用于特定的错误及应用领域 |
日志的级别
级别 |
何时使用 |
DEBUG |
细节信息,仅当诊断问题时适用。 |
INFO |
确认程序按预期运行。 |
WARNING |
表明有已经或即将发生的意外(例如:磁盘空间不足)。程序仍按预期进行。 |
ERROR |
由于严重的问题,程序的某些功能已经不能正常执行 |
CRITICAL |
严重的错误,表明程序已不能继续执行 |
示例
基础用法
1
2
3
|
import logging
logging.warning('Watch out!') # 将打印一条消息到控制台
logging.info('I told you so') # 将不打印任何消息
|
INFO
消息没有出现是因为默认级别
为 WARNING
在这个例子中,我们是直接使用 logging 模块的函数,比如 logging.debug
,而不是创建一个日志记录器并调用其方法。 这些函数是在根日志记录器上操作的,但它们在未被调用时将会调用 basicConfig()
来发挥作用,就像在这个例子中那样。 然而在更大的程序中你通常会需要显式地控制日志记录的配置 —— 所以出于这样那样的理由,最好还是创建日志记录器并调用其方法
记录日志到文件
1
2
3
4
5
6
7
|
import logging
logger = logging.getLogger(__name__)
logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.DEBUG)
logger.debug('This message should go to the log file')
logger.info('So should this')
logger.warning('And this, too')
logger.error('And non-ASCII stuff, too, like Øresund and Malmö')
|
上面的示例将日志事件记录到文件
中并设置了日志等级
显示消息的格式
1
2
3
4
5
|
import logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
logging.debug('This message should appear on the console')
logging.info('So should this')
logging.warning('And this, too')
|
在消息中显示日期/时间
1
2
3
|
import logging
logging.basicConfig(format='%(asctime)s %(message)s')
logging.warning('is when this event was logged.')
|
进阶日志教程
日志库采用模块化方法,并提供几类组件:记录器、处理器、过滤器和格式器。
- 记录器暴露了应用程序代码直接使用的接口。
- 处理器将日志记录(由记录器创建)发送到适当的目标。
- 过滤器提供了更细粒度的功能,用于确定要输出的日志记录。
- 格式器指定最终输出中日志记录的样式。
最佳实践
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
29
30
31
32
33
34
35
36
37
38
|
import logging
import os
# 日志文件路径
LOG_DIR = "logs"
os.makedirs(LOG_DIR, exist_ok=True) # 确保日志目录存在
LOG_FILE = os.path.join(LOG_DIR, "app.log")
# 创建日志器(全局使用)
logger = logging.getLogger("my_app")
logger.setLevel(logging.DEBUG) # 设置最低日志级别
# 创建格式化器(统一日志格式)
formatter = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
# 创建控制台 Handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO) # 仅输出 INFO 及以上的日志
console_handler.setFormatter(formatter)
# 创建文件 Handler
file_handler = logging.FileHandler(LOG_FILE, encoding="utf-8")
file_handler.setLevel(logging.DEBUG) # 记录所有级别的日志
file_handler.setFormatter(formatter)
# 绑定 Handler(避免重复添加)
if not logger.handlers:
logger.addHandler(console_handler)
logger.addHandler(file_handler)
# 测试日志
logger.debug("这是一条 DEBUG 日志")
logger.info("这是一条 INFO 日志")
logger.warning("这是一条 WARNING 日志")
logger.error("这是一条 ERROR 日志")
logger.critical("这是一条 CRITICAL 日志")
|