import logging
logging.basicConfig(level=logging.DEBUG, format=' %(asctime)s - %(levelname)s - %(message)s')
你不需要过于担心它的工作原理,但基本上,
当 Python 记录一个事件的日志时,
它会创建一个 LogRecord
对象,保存关于该事件的信息。
logging
模块的函数让你指定想看到的
这个 LogRecord
对象的细节,
以及希望的细节展示方式。
假如你编写了一个函数,计算一个数的阶乘。
在数学上,4的阶乘是 1 x 2 x 3 x 4
,即 24
。
7的阶乘是 1 x 2 x 3 x 4 x 5 x 6 x 7
,即 5040
。
打开一个新的文件编辑器窗口,输入以下代码。其中有一个缺陷,
但你也会输入一些日志信息,
帮助你弄清楚哪里出了问题。。
import logging
logging.basicConfig(level=logging.DEBUG,
format=' %(asctime)s - %(levelname)s - %(message)s')
logging.debug('Start of program')
2025-04-21 01:44:28,240 - DEBUG - Start of program
def factorial(n):
logging.debug('Start of factorial(%s%%)' % (n))
total = 1
for i in range(n + 1):
total *= i
logging.debug('i is ' + str(i) + ', total is ' + str(total))
logging.debug('End of factorial(%s%%)' % (n))
return total
print(factorial(5))
logging.debug('End of program')
2025-04-21 01:44:30,724 - DEBUG - Start of factorial(5%) 2025-04-21 01:44:30,725 - DEBUG - i is 0, total is 0 2025-04-21 01:44:30,725 - DEBUG - i is 1, total is 0 2025-04-21 01:44:30,726 - DEBUG - i is 2, total is 0 2025-04-21 01:44:30,726 - DEBUG - i is 3, total is 0 2025-04-21 01:44:30,727 - DEBUG - i is 4, total is 0 2025-04-21 01:44:30,727 - DEBUG - i is 5, total is 0 2025-04-21 01:44:30,727 - DEBUG - End of factorial(5%) 2025-04-21 01:44:30,728 - DEBUG - End of program
0
这里,在想打印日志信息时,使用 logging.debug()
函数。
这个 debug()
函数将调用 basicConfig()
,
打印一行信息。这行信息的格式是在 basicConfig()
函数
中指定的,并且包括传递给 debug()
的消息。
print(factorial(5))
调用是原来程序的一部分,
所以就算禁用日志信息,结果仍会显示。
这个程序的输出就像这样。
factorial()
函数返回0作为5的阶乘,这是不对的。
for
循环应该用从1到5的数,乘以 total
的值。
但 logging.debug()
显示的日志信息表明,
i
变量从0开始,而不是1。因为0乘任何数都是0,
所以接下来的迭代中, total
的值都是错的。
日志消息提供了可以追踪的痕迹,
帮助你弄清楚何时事情开始不对。
将代码行 for i in range (n + 1):
改为
for i in range (1,n + 1):
,
再次运行程序。 输出看起来像这样:
import logging
logging.basicConfig(level=logging.DEBUG,
format=' %(asctime)s - %(levelname)s - %(message)s')
logging.debug('Start of program')
2025-04-21 01:44:32,686 - DEBUG - Start of program
def factorial(n):
logging.debug('Start of factorial(%s%%)' % (n))
total = 1
for i in range(1,n + 1):
total *= i
logging.debug('i is ' + str(i) + ', total is ' + str(total))
logging.debug('End of factorial(%s%%)' % (n))
return total
print(factorial(5))
logging.debug('End of program')
2025-04-21 01:44:35,749 - DEBUG - Start of factorial(5%) 2025-04-21 01:44:35,750 - DEBUG - i is 1, total is 1 2025-04-21 01:44:35,750 - DEBUG - i is 2, total is 2 2025-04-21 01:44:35,751 - DEBUG - i is 3, total is 6 2025-04-21 01:44:35,751 - DEBUG - i is 4, total is 24 2025-04-21 01:44:35,751 - DEBUG - i is 5, total is 120 2025-04-21 01:44:35,752 - DEBUG - End of factorial(5%) 2025-04-21 01:44:35,752 - DEBUG - End of program
120
import logging
logging.basicConfig(level = logging.DEBUG,
format ='%(asctime)s - %(levelname)s- %(message)s')
你可能想使用 print()
调用代替,但不要屈服于这种诱惑!
在调试完成后,你需要花很多时间,从代码中清除每条日志消息的 print()
调用。
你甚至有可能不小心删除一些 print()
调用,而它们不是用来产生日志消息的。
日志消息的好处在于,你可以随心所欲地在程序中想加多少就加多少,
稍后只要加入一次 logging.disable(logging.CRITICAL)
调用,就可以禁止日志。
不像 print()
,logging
模块使得显示和隐藏日志信息之间的切换变得很容易。
日志消息是给程序员的,不是给用户的。用户不会因为便于调试,
而想看到的字典值的内容。
对于用户希望看到的消息,例如 “文件未找到” 或者 “无效的输入,请输入一个数字” ,
应该使用 print()
调用。
不希望禁用日志消息之后,让用户看不到有用的信息。
日志级别
“日志级别”提供了一种方式,按重要性对日志消息进行分类。 5个日志级别如下表所示,从最不重要到最重要。 利用不同的日志函数,消息可以按某个级别记入日志。
级别 | 日志函数 | 描述 |
---|---|---|
DEBUG | logging.debug() | 最低级别。通常只有在调试程序时,你才会关心这些消息 |
INFO | logging.info() | 用于记录程序中一般事件的信息,或确认一切工作正常 |
WARNING | logging.warning() | 用于表示可能的问题 |
ERROR | logging.error() | 用于记录错误,它导致程序做某事失败 |
CRITICAL | logging.critical() | 最高级别。用于表示致命的错误 |
日志消息作为一个字符串,传递给这些函数。日志级别是一种建议。归根到底, 还是由你来决定日志消息属于哪一种类型。在交互式环境中输入以下代码:
import logging
logging.basicConfig(level=logging.DEBUG,
format=' %(asctime)s -%(levelname)s - %(message)s')
logging.debug('Some debugging details.')
2025-04-21 01:44:40,277 - DEBUG - Some debugging details.
logging.info('The logging module is working.')
2025-04-21 01:44:42,613 - INFO - The logging module is working.
logging.warning('An error message is about to be logged.')
2025-04-21 01:44:43,829 - WARNING - An error message is about to be logged.
logging.error('An error has occurred.')
2025-04-21 01:44:45,332 - ERROR - An error has occurred.
logging.critical('The program is unable to recover!')
2025-04-21 01:44:46,599 - CRITICAL - The program is unable to recover!
日志级别的好处在于,你可以改变想看到的日志消息的优先级。
向 basicConfig()
函数传入 logging.DEBUG
作为
level
关键字参数,这将显示所有日志级别的消息
(DEBUG
是最低的级别)。但在开发了更多的程序后,你可能只对错误感兴趣。
在这种情况下,可以将 basicConfig()
的 level
参数设置为 logging.ERROR
,
这将只显示 ERROR
和 CRITICAL
消息,跳过 DEBUG
、INFO
和 WARNING
消息。
禁用日志
在调试完程序后,可能不希望所有这些日志消息出现在屏幕上。
logging.disable()
函数禁用了这些消息,
这样就不必进入到程序中,手工删除所有的日志调用。
只要向 logging.disable()
传入一个日志级别,它就会禁止该级别和更低级别的所有日志消息。
所以,如果想要禁用所有日志,只要在程序中添加 logging.disable(logging.CRITICAL)
。
例如,在交互式环境中输入以下代码:
import logging
logging.basicConfig(level=logging.INFO,
format=' %(asctime)s -%(levelname)s - %(message)s')
logging.critical('Critical error! Critical error!')
2025-04-21 01:44:48,563 - CRITICAL - Critical error! Critical error!
logging.disable(logging.CRITICAL)
logging.critical('Critical error! Critical error!')
logging.error('Error! Error!')
import logging
logging.basicConfig(filename='myProgramLog.txt',
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s')
日志信息将被保存到 myProgramLog.txt
文件中。
虽然日志消息很有用,但它们可能塞满屏幕,很难读到程序的输出。
将日志信息写入到文件,让屏幕保持干净,又能保存信息,
这样在运行程序后,可以阅读这些信息。
可以用任何文件编辑器打开这个文本文件。
import logging
logging.basicConfig(level=logging.DEBUG,
format=' %(asctime)s - %(levelname)s - %(message)s')
logging.debug('Start of program')
def factorial(n):
logging.debug('Start of factorial(%s%%)' % (n))
total = 1
for i in range(1,n + 1):
total *= i
logging.debug('i is ' + str(i) + ', total is ' + str(total))
logging.debug('End of factorial(%s%%)' % (n))
return total
print(factorial(5))
logging.debug('End of program')
120