使用logging模块debug方法来调试代码

一般的小代码,初学者可能会采取在适当的地方添加print()方法输出信息来进行代码的检查和调试,但是如果代码比较多,print()方法在调试完成后需要将所有的print()代码都注释或者删除以使得调试输出信息不再输出,这对于大代码非常不方便。因此最好不要养成使用print()语句调试的习惯,一开始就学习使用logging模块debug方法来调试代码。

python系统自带logging模块可以实现对代码的运行追踪的日志记录功能,提供了便捷的代码bug追踪机制,不仅可以将日志打印出来,还可以将日志保存为文档,便于保存与查看。开发人员可以对他们的代码添加日志调用,借此来指示某事件的发生。一个事件通过一些包含变量数据的描述信息来描述(比如:每个事件发生时的数据都是不同的)。logging模块还提供区分事件的重要性的不同级别:

级别级别数值使用时机
DEBUG10详细信息,常用于调试。
INFO20程序正常运行过程中产生的一些信息。
WARNING30警告用户,虽然程序还在正常工作,但有可能发生错误。
ERROR40由于更严重的问题,程序已不能执行一些功能了。
CRITICAL50严重错误,程序已不能继续运行。

logging的默认的级别是WARNING,意味着只会追踪该级别及以上的事件,DEBUG和INFO会被忽略,WARING、ERROR和CRITICAL会被记录,除非更改日志配置。

一个简单的将结果输出到控制台的语句为:

import logging
logging.warning('info level')  # WARNING:root:info levelb

有多种方法用来处理被跟踪的事件。最简单的方法就是把它们打印到终端控制台上:

import logging
from logging import debug

logging.basicConfig(format='%(levelname)s:%(funcName)s:%(message)s', level = logging.DEBUG)

def func(s):
    str1 = 'Loop'
    str2 = 'leap'
    debug(f's的数据类型为 {type(s)}, {s}')
    debug(f'{str1} before you {str2}')
    return s/10  
 
if __name__ == '__main__':
    func(100)

输出结果为:

DEBUG:func:s的数据类型为 <class 'int'>, 100
DEBUG:func:Loop before you leap

basicConfig方法介绍

在使用过程中可以直接用logging.debug()来替换print()。如果程序调试好,可以通过修改level来控制debug info的输出, eg:将以下这句的level = logging.DEBUG换为logging.INFO就可以了:

logging.basicConfig(format='%(levelname)s:%(funcName)s:%(message)s', level = logging.INFO)

basicConfig方法中的format定义了日志信息中包含的信息的格式,变量是logging内置的keys:

属性格式描述
asctime%(asctime)s日志产生的时间,默认格式为2003-07-08 16:49:45,896
created%(created)ftime.time()生成的日志创建时间戳
funcName%(funcName)s调用日志的函数名
levelname%(levelname)s日志级别 (‘DEBUG’, ‘INFO’, ‘WARNING’, ‘ERROR’, ‘CRITICAL’)
lineno%(lineno)d日志所针对的代码行号(如果可用的话)
module%(module)s生成日志的模块名
message%(message)s具体的日志信息
name%(name)s日志调用者

我们还可以通过basicConfig方法中的参数设置,将结果输出到文件:

import logging
logging.basicConfig(filename='test.log', level=20)
logging.log(10, '级别为10的一条日志')
logging.log(20, '级别为20的一条日志')

上例中,通过basicConfig方法将日志输出到test.log文件,并且设置只有级别大于等于20的才会写入到该日志文件。也就是说,上例中,第一条级别为10的日志将不会写入到文件。并且,需要注意的是,如果你查看日志文件,如果出现乱码的话,请检查编码方式。

上例中,在basicConfig方法中,级别20也可以这样指定:

logging.basicConfig(filename='test.log', level=logging.INFO) 
logging.debug('debug level: 10')
logging.info('info level: 20')
logging.warning('warning level: 30')
logging.error('error level: 40')
logging.critical('critical level: 50')

上例中同样只有级别大于等于20的将会被写入文件test.log。

basicConfig方法还可以指定一下参数:

  • filemode,日志文件写入方式,可以是w和a,默认的是a模式。
  • datefmt,指定时间的输出格式。
  • level,指定日志输出的类别,程序会输出大于等于此级别的信息。
  • stream,在没有指定filename的时候会默认使用StreamHandler,这时stream可以指定初始化的文件流。
  • handlers:可以指定日志处理时所使用的 Handlers,必须是可迭代的。

示例:

import logging
logging.basicConfig(
    filename='test.log',
    filemode='w',
    level=logging.DEBUG,
    datefmt='%Y/%m/%d %H:%M:%S',
    format='%(asctime)s - %(name)s - %(levelname)s - %(lineno)d - %(module)s - %(message)s'
)
logging.debug('debug level: 10')
logging.info('info level: 20')
logging.warning('warning level: 30')
logging.error('error level: 40')
logging.critical('critical level: 50')

输出结果为:

2019/05/30 14:38:09 - root - DEBUG - 36 - 日志模块 - debug level: 10
2019/05/30 14:38:09 - root - INFO - 37 - 日志模块 - info level: 20
2019/05/30 14:38:09 - root - WARNING - 38 - 日志模块 - warning level: 30
2019/05/30 14:38:09 - root - ERROR - 39 - 日志模块 - error level: 40
2019/05/30 14:38:09 - root - CRITICAL - 40 - 日志模块 - critical level: 50

需要注意的是,logging.basicConfig只生效一次,比如:
···
import logging
logging.basicConfig(
filename=‘test1.log’,
filemode=‘w’,
level=logging.DEBUG
)

无效

logging.basicConfig(
filename=‘test2.log’,
filemode=‘a’,
level=logging.INFO
)

logging.debug(‘debug level: 10’)
logging.info(‘info level: 20’)
logging.warning(‘warning level: 30’)
logging.error(‘error level: 40’)
logging.critical(‘critical level: 50’)
···
正如上例所示,我们配置了两次basicConfig。但如果运行你会发现,只有第一个配置生效了,第二个配置不会生效。原因是当在第一次配置的时候,logging在内部就会进行配置,第二次再次配置的时候,logging就会认为我已经配置好了,不需要再次配置了。

Debug 简易使用

首先使用logging.getLogger()进行配置,参数为文件名,通过logger.setLevel()设置logger的级别:

import logging

# 配置logger并设置等级为DEBUG
logger = logging.getLogger('logging_debug')
logger.setLevel(logging.DEBUG)

然后使用logging.StreamHandler()方法初始化consoleHandler,通过consoleHandler.setLevel()设置级别:

# 配置控制台Handler并设置等级为DEBUG
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.DEBUG)

再通过logger.addHandler()方法将consoleHandler加入logger,完成logger的配置:

logger.addHandler(consoleHandler)

完整代码:

import logging

# 配置logger并设置等级为DEBUG
logger = logging.getLogger('logging_debug')
logger.setLevel(logging.DEBUG)
# 配置控制台Handler并设置等级为DEBUG
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.DEBUG)
# 将Handler加入logger
logger.addHandler(consoleHandler)

logger.debug('This is a logging.debug')

输出结果:
This is a logging.debug
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值