Python学习:日志

日志

如果你曾经在代码中加入 print() 语句,在程序运行时输出某些变量的值,你就使用了记日志的方式来调试代码。记日志是一种很好的方式,可以理解程序中发生的事,以及事情发生的顺序。 Python 的 logging 模块使得你很容易创建自定义的消息记录。这些日志消息将描述程序执行何时到达日志函数调用,并列出你指定的任何变量当时的值。另一方面,缺失日志信息表明有一部分代码被跳过,从未执行。

使用日志模块

要启用logging 模块,在程序运行时将日志信息显示在屏幕上,请将下面的代码复制到程序顶部(但在 Python 的#!行之下):

import logging
logging.basicConfig(
	level=logging.DEBUG, 
	format=' %(asctime)s - %(levelname)s- %(message)s'# 日志打印格式
	)

基本上,当 Python 记录一个事件的日志时,它会创建一个 LogRecord 对象,保存关于该事件的信息。 logging 模块的函数让你指定想看到的这个 LogRecord 对象的细节,以及希望的细节展示方式。
假如你编写了一个函数,计算一个数的阶乘。在数学上, 4 的阶乘是1 × 2 × 3 × 4,即 24。 7 的阶乘是 1 × 2 × 3 × 4 × 5 × 6 × 7,即 5040。打开一个新的文件编辑器窗口,输入以下代码。其中有一个缺陷,但你也会输入一些日志信息,帮助你弄清楚哪里出了问题。

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(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')
输出:
0
 2019-06-17 14:17:35,350 - DEBUG- Start of program
 2019-06-17 14:17:35,350 - DEBUG- Start of factorial(5%)
 2019-06-17 14:17:35,350 - DEBUG- i is 0, total is 0
 2019-06-17 14:17:35,350 - DEBUG- i is 1, total is 0
 2019-06-17 14:17:35,350 - DEBUG- i is 2, total is 0
 2019-06-17 14:17:35,350 - DEBUG- i is 3, total is 0
 2019-06-17 14:17:35,350 - DEBUG- i is 4, total is 0
 2019-06-17 14:17:35,350 - DEBUG- i is 5, total is 0
 2019-06-17 14:17:35,350 - DEBUG- End of factorial(5%)
 2019-06-17 14:17:35,350 - DEBUG- End of program

打印日志信息时,使用 logging.debug() 函数。这个 debug() 函数将调用 basicConfig(),打印一行信息。这行信息的格式是我们在 basicConfig()函数中指定的,并且包括我们传递给 debug() 的消息。

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):,再次运行程序。
输出看起来像这样:

	输出:
	120
	 2019-06-17 14:22:30,612 - DEBUG- Start of program
	 2019-06-17 14:22:30,612 - DEBUG- Start of factorial(5%)
	 2019-06-17 14:22:30,612 - DEBUG- i is 1, total is 1
	 2019-06-17 14:22:30,612 - DEBUG- i is 2, total is 2
	 2019-06-17 14:22:30,612 - DEBUG- i is 3, total is 6
	 2019-06-17 14:22:30,612 - DEBUG- i is 4, total is 24
	 2019-06-17 14:22:30,612 - DEBUG- i is 5, total is 120
	 2019-06-17 14:22:30,612 - DEBUG- End of factorial(5%)
	 2019-06-17 14:22:30,612 - DEBUG- End of program

日志级别

“日志级别”提供了一种方式,按重要性对日志消息进行分类。 5 个日志级别如表所示,从最不重要到最重要。利用不同的日志函数,消息可以按某个级别记入日志。
在这里插入图片描述
在这里插入图片描述
日志的级别

import logging  
logging.debug('debug message')  
logging.info('info message')  
logging.warning('warning message')  
logging.error('error message')  
logging.critical('critical message')  

灵活配置日志级别,日志格式,输出位置

除了将日志消息显示在屏幕上,还可以将它们写入文本文件。 logging.basicConfig() 函数接受 filename 关键字参数,

import logging
logging.basicConfig(
	filename='myProgramLog.txt', 
	level=logging.DEBUG, 
	format='%(asctime)s - %(levelname)s - %(message)s'
	)

日志信息将被保存到 myProgramLog.txt 文件中。虽然日志消息很有用,但它们可能塞满屏幕,让你很难读到程序的输出。将日志信息写入到文件,让屏幕保持干净,又能保存信息,这样在运行程序后,可以阅读这些信息。可以用任何文件编辑器打开这个文本文件,诸如 Notepad 或 TextEdit。
日志文本默认的是追加方式进行写入的,可以更改写入的方式filemode=‘w

logging.basicConfig(
	filename='myProgramLog.txt',
	level=logging.DEBUG,
	format='%(asctime)s - %(levelname)s - %(message)s',
    filemode='w'
    )

logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有

  • filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。
  • filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
  • format:指定handler使用的日志显示格式。
  • datefmt:指定日期时间格式。
  • level:设置rootlogger的日志级别
  • stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,‘w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
import logging  
logging.basicConfig(level=logging.DEBUG,  
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',  
                    datefmt='%a, %d %b %Y %H:%M:%S',  
                    filename='test.log',  
                    filemode='w')  
  
logging.debug('debug message')  
logging.info('info message')  
logging.warning('warning message')  
logging.error('error message')  
logging.critical('critical message')

输出:test.log
在这里插入图片描述
format参数中可能用到的格式化串:

  • %(name)s Logger的名字
  • %(levelno)s 数字形式的日志级别
  • %(levelname)s 文本形式的日志级别
  • %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
  • %(filename)s 调用日志输出函数的模块的文件名
  • %(module)s 调用日志输出函数的模块名
  • %(funcName)s 调用日志输出函数的函数名
  • %(lineno)d 调用日志输出函数的语句所在的代码行
  • %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
  • %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
  • %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
  • %(thread)d 线程ID。可能没有
  • %(threadName)s 线程名。可能没有
  • %(process)d 进程ID。可能没有
  • %(message)s用户输出的消息

logger对象

上述几个例子中我们了解到了logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical()(分别用以记录不同级别的日志信息),logging.basicConfig()(用默认日志格式(Formatter)为日志系统建立一个默认的流处理器(StreamHandler),设置基础配置(如日志级别等)并加到root logger(根Logger)中)这几个logging模块级别的函数,另外还有一个模块级别的函数是logging.getLogger([name])(返回一个logger对象,如果没有指定名字将返回root logger)

一个最简单的过程:

import logging

logger = logging.getLogger()

# 创建一个handler,用于写入日志文件
fh = logging.FileHandler('test11.log',mode='w')

# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

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

logger.addHandler(fh)  #logger对象可以添加多个fh和ch对象
logger.addHandler(ch)
logger.setLevel(logging.DEBUG) #设置日志的级别。对于低于该级别的日志消息将被忽略.



logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')
  • FileHandler(StreamHandler):
    A handler class which writes formatted logging records to disk files.
    def init(self, filename, mode=‘a’, encoding=None, delay=False):

  • logging库提供了多个组件:Logger、HandlerFilterFormatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。

  • Logger是一个树形层级结构,输出信息之前都要获得一个Logger(如果没有显示的获取则自动创建并使用root Logger,)。 logger = logging.getLogger()返回一个默认的Logger也即root Logger,并应用默认的日志级别、Handler和Formatter设置。
    当然也可以通过Logger.setLevel(lel)指定最低的日志级别,可用的日志级别有logging.DEBUG、``logging.INFOlogging.WARNINGlogging.ERRORlogging.CRITICAL

  • Logger.debug()Logger.info()Logger.warning()Logger.error()Logger.critical()输出不同级别的日志,只有日志等级大于或等于设置的日志级别的日志才会被输出

可以将上述logging进行函数化

import logging
def logger():
    logger = logging.getLogger()

    # 创建一个handler,用于写入日志文件
    fh = logging.FileHandler('test10.log',mode='w')

    # 再创建一个handler,用于输出到控制台
    ch = logging.StreamHandler()

    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

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

    logger.addHandler(fh)  #logger对象可以添加多个fh和ch对象
    logger.addHandler(ch)
    logger.setLevel(logging.DEBUG) #设置日志的级别。对于低于该级别的日志消息将被忽略.

    return  logger


logger=logger()

logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值