python 日志模块总结

Python 的 logging 模块是 Python 标准库的一部分,它提供了一个灵活的框架来将日志信息发送到不同的目的地,如控制台、文件、远程服务器等。使用 logging 模块,你可以控制日志信息的级别,并且可以针对不同的应用模块进行日志管理。

1. 日志级别

  • DEBUG: 调试信息,用于问题诊断。
  • INFO: 一般信息,用于记录程序运行状态。
  • WARNING: 警告信息,表示有潜在问题。
  • ERROR: 错误信息,表示严重问题。
  • CRITICAL: 临界信息,表示非常严重的问题。

日志级别默认为 WARNING,从大到小为:

CRITICAL > ERROR > WARNING > INFO > DEBUG

输出的日志是设置的日志级别及其以上级别:

如果设置的日志级别为 WARNING,则只会显示 WARNING 及其以上级别的信息:WARNING, ERROR, CRITICAL

2. 简单🌰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import logging

# log 文件路径
log_file = 'demo_log.log'

# log 输出格式,格式有很多,这个是常用的格式,不够用在查
log_format = '%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s : %(message)s'

logging.basicConfig(filename=log_file, # 设置 log 输出文件
level=logging.DEBUG, # 输出等级
format=log_format, # 输出格式
filemode='w') # 日志文件打开模式 w是写入,a是追加

logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')

结果:

1
2
3
4
2024-08-08 11:33:40,649 - demo_log0.py[line:16] - INFO : This is an info message
2024-08-08 11:33:40,649 - demo_log0.py[line:17] - WARNING : This is a warning message
2024-08-08 11:33:40,649 - demo_log0.py[line:18] - ERROR : This is an error message
2024-08-08 11:33:40,649 - demo_log0.py[line:19] - CRITICAL : This is a critical message

3. 高级🌰

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
39
import logging, os

log_path = os.path.join(os.path.dirname(__file__), 'demo_log.log')

# 创建一个 log 对象
logger = logging.getLogger('__name__') # 其中的__name__代表当前 py 文件的名称,也可以不写
# 设置 log 对象的等级,记录所有文件级别日志
logger.setLevel(logging.DEBUG)

# 创建一个 FileHandler,将写入文件
fh = logging.FileHandler(log_path, mode='w')
# 设置log 等级,记录所有文件级别日志
fh.setLevel(logging.DEBUG)

# 创建一个 StreamHandler, 将 log 输出到控制台
ch = logging.StreamHandler()
# 设置 log 等级,控制台只记录 Error 以及以上的记录
ch.setLevel(logging.ERROR)

# 设置输出格式
log_formatter = '%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s : %(message)s'
formatter = logging.Formatter(log_formatter)

ch.setFormatter(formatter)
fh.setFormatter(formatter)

# 把handler添加到 logger 里
logger.addHandler(ch)
logger.addHandler(fh)

logger.error('error message')
logger.debug('debug message')

# 干完之后清理下,这里主要为了以后多次调用出现重复日志输出
# logger.removeHandler(ch)
# logger.removeHandler(fh)

# logger.error('error message')

在这个示例中,我们创建了一个 Logger 对象,并设置了两个 Handler:一个输出到控制台的 StreamHandler 和一个输出到文件的 FileHandler。我们还定义了一个 Formatter 来格式化日志消息,并将其应用到了两个 Handler 上。最后,我们添加了日志消息,它们会根据设置的日志级别被输出到相应的目的地。

4. 封装后使用

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
39
# demo_log2.py
import logging, os


def demo_log2():
log_path = os.path.join(os.path.dirname(__file__), 'demo_log.log')

# 创建一个 log 对象
logger = logging.getLogger('__name__') # 其中的__name__代表当前 py 文件的名称,也可以不写
logger.handlers.clear() # 防止重复输出日志,因为添加一个 handler就会输出一次
# 设置 log 对象的等级
logger.setLevel(logging.DEBUG)

# 创建一个 handler,将写入文件
fh = logging.FileHandler(log_path, mode='a')
# 设置log 等级与前面保持一致
fh.setLevel(logging.DEBUG)

# 创建一个 handler, 将 log 输出到控制台
ch = logging.StreamHandler()
# 设置 log 等级与 log 对象保持一致
ch.setLevel(logging.ERROR)

# 设置输出格式
log_formatter = '%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s : %(message)s'
formatter = logging.Formatter(log_formatter)
ch.setFormatter(formatter)
fh.setFormatter(formatter)

# 把handler添加到 logger 里
# print(logger.handlers) # 没添加时,logger.handlers == []
# 如果 logger.handlers 为空,则添加 ch / fh ,防止重复输出日志,因为添加一个 handler就会输出一次
# if logger.handlers.__len__() == 0:
logger.addHandler(ch)
logger.addHandler(fh)
# print(logger.handlers)

return logger

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# demo_user_log.py

import demo_log2


def calc_sum(a, b):

logger = demo_log2.demo_log2()

try:
sum = a / b
logger.debug(f'{a} / {b} = {sum} ')
return sum
except ZeroDivisionError as e:
logger.error(f'被除数不能为 0: {e}')

if __name__ == '__main__':
calc_sum(1,1)
calc_sum(1,0)

输出结果:

控制台输出结果:

1
2024-08-08 15:13:56,611 - demo_user_log.py[line:13] - ERROR : 被除数不能为 0: division by zero

日志文件输出结果:

1
2
2024-08-08 15:13:56,611 - demo_user_log.py[line:10] - DEBUG : 1 / 1 = 1.0 
2024-08-08 15:13:56,611 - demo_user_log.py[line:13] - ERROR : 被除数不能为 0: division by zero