Python--日志模块Logging

来源:互联网 发布:对上知教育的评价 编辑:程序博客网 时间:2024/05/22 03:47
日志在程序中是很重要且必要的,有良好日志记录的程序,在定位问题的时候能快速帮你找到问题的原因。
Python标准库的Logging提供了一些方便的函数,有debug()、info()、warning()、error()和critical()。可以很方便的在程序中使用它们。
执行的动作最好的方式在一个命令行脚本或程序中显示使用说明到控制台print()报告一个程序在正常操作时发生的事logging.info()(或logging.debug()输出更详细的信息为了诊断程序运行时的问题警告logging.waring(),客户端不能做什么,但是这个事件需要被记录报告运行式的错误抛出一个异常报告一个错误发生时的处理建议logging.error()、logging.exception()或logging.critical()

标准的日志级别和它们的适用性描述如下:
LevelWhen it's usedDEBUG详细信息,诊断程序的时候使用INFO证明程序如期望般运行着WARNING表明某些事发生在意料之外或在不久的将发生问题ERROR表明相对严重的问题,软件没有能力执行一些功能CRITICAL很严重的问题,软件无法继续执行
默认级别是WARNING
简单的例子:
import logginglogging.warning('Watch out!')  # 将会输出logging.info('I told you so')  # 将不会输出
记录日志到文件
常见的是把日志记录到文件中。
import logginglogging.basicConfig(filename='example.log', level=logging.DEBUG)logging.debug('This message should go to the log file')logging.info('So should this')logging.warning('And this,too')
多个模块中使用logging
# myapp.pyimport loggingimport mylibdef main():    logging.basicConfig(filename='myapp.log', level=logging.INFO)    logging.info('Started')    mylib.do_something()    logging.info('Finished')if __name__ == '__main__':    main()# mylib.pyimport loggingdef do_something():    logging.info('Doing something')
当运行myapp.py,在myapp.log中将看到如下信息:
INFO:root:Started
INFO:root:Doing something
INFO:root:Finished
这只是 简单的用法,不能知道日志来自哪个模块。
日志中变量数据
import logging
logging.warning(' %s before you %s', 'Look', 'leap!')
输出:
WARNING:root:Look before you leap!
日志记录的格式
import logginglogging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)logging.debug('This message should apear on the console')logging.info('So should this')logging.warning('And this,too')
在日志中显示时间
import logginglogging.basicConfig(format='%(asctime)s %(message)s')logging.warning('is when this event was logged')
输出:
2017-06-25 17:14:32,825 is when this event was logged
定制日期显示格式:
import logginglogging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')logging.warning('is when this event was logged.')
输出:
12/12/2010 11:46:36 AM is when this event was logged.
datefmt的参数和time.strftime()支持的一样
高级日志教程
logging库提供了一些模块方法和组件:loggers、handlers、filters和formatters。
  • Loggers暴露接口给应用直接使用
  • Handlers发送日志(loggers生成的)到正确的目的地
  • Filters决定哪些日志被记录输出
  • Formatters指定日志显示的格式
日志事件信息通过loggers,handlers,filters和formatters成为一个LogRecord实例。
一个好的习惯是使用模块级logger,定义如下:
logger = logging.getLogger(__name__)
Loggers
Loggers对象有三重作用
第一,暴露一些方法给应用代码,以便应用在运行时可以记录日志。
第二,logger对象决定了哪些日志信息在日志级别和过滤器之上。
第三,logger对象传递有关的日志信息给感兴趣的log handlers。

最广泛使用logger分为两类:配置和信息发送
下面是几个最常用的logger配置方法:
  • Logger.setLevel() 指定一个logger将处理的日志级别
  • Logger.addHandler()和Logger.removeHandler() 从logger对象中添加和删除handler
  • Logger.addFilter()和Logger.removeFilter() 从logger对象中添加和删除filter对象
当logger被配置后,下面的方法将创建日志信息:
  • Logger.debug()、Logger.info()、Logger.warning()、Logger.error()和Logger.critical()
  • Logger.exception() 创建一个类似Logger.error()的日志信息,不同点是Logger.exception()会输出堆栈信息
  • Logger.log()
getLogger()返回一个指向logger实例的引用(如果提供名字的话就返回特定名字,没有的话为root)。
Handlers
Handler对象可靠的分发正确的日志给handler所指定的目的地。Logger对象可以使用addHandler()方法添加0个或多个handler给自己,比如一个使用场景是,应用想发送所有的日志给一个日志文件,error或更高级别的日志发送到标准输出,critical日志以邮件发送。这种场景需要三个handler,分别发送日志到指定地方。
  • setLevel() 和logger对象的一样,指定日志的级别,这里为什么会有两个setLevel()方法呢?logger对象设置的日记级别决定哪些级别的日志会传到它的handler(),每个handler设置的日志级别决定哪些级别的日志会被发送到目的地。
  • setFormatter() handler选择一个Formatter对象去使用。
  • addFilter()和removeFilter()每个handler分别配置和取消配置filter对象。
应用程序不应该直接使用Handler对象的实例,而是Handler作为基类,为子类定义行为一致的接口。
Formatters
Formatter对象配置最终日志的顺序、结构和内容,不像基类logging.Handler,应用程序代码可以实例化formatter类,如果你需要特别的行为,你也可以使用formatter的子类。Formatter的构造器有三个可选参数,一个日志格式字符串,一个时间日期格式字符串和一个风格指示器。
logging.Formatter.__init__(fmt=None,datefmt=None,style='%')
如果没有format字符串,默认使用行消息
如果没有时间日志格式字符串,默认使用的格式如下:
%Y-%m-%d %H:%M:%S
style有三种:%,'{'或‘$',如果没有指定,默认是%
如果style是%,消息格式字符串时使用%(<dictionary key>)s 去替换;
如果style是'{ ',消息字符串的格式被假定和str.format()一致(使用关键字参数)
如果style是’$',消息字符串的格式符合string.Template.substiute()定义的

配置Logging
程序配置logging有以下三种方式:
1. 使用上面介绍的配置方法创建loggers,handlers和formatters
2. 创建一个日志配置文件然后使用fileConfig()去读取。
3. 创建一个字典配置信息然后使用dictConfig()去解析。
import logging# create loggerlogger = logging.getLogger('simple_example')logger.setLevel(logging.DEBUG)# create console handler and set level to debugch = logging.StreamHandler()ch.setLevel(logging.DEBUG)# create formatterformatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# add formatter to chch.setFormatter(formatter)# add ch to loggerlogger.addHandler(ch)# 'application' codelogger.debug('debug message')logger.info('info message')logger.warn('warn message')logger.error('error message')logger.critical('critical message')
输出:
$ python simple_logging_module.py
2005-03-19 15:10:26,618 - simple_example - DEBUG - debug message
2005-03-19 15:10:26,620 - simple_example - INFO - info message
2005-03-19 15:10:26,695 - simple_example - WARNING - warn message
2005-03-19 15:10:26,697 - simple_example - ERROR - error message
2005-03-19 15:10:26,773 - simple_example - CRITICAL - critical message

一些有用的Handler

除了基类Handler之外,下面是一些很有用的子类:
1. StreamHandler--实例发送消息到流(file-like对象)
2. FileHandler--实例发送消息到磁盘文件
3. BaseRotatingHandler--绕接日志文件的基类,不能被直接实例化,使用RotatingFileHandler或TimeRotatingFileHandler
4. RotatingFileHandler--发送消息到磁盘文件并支持日志文件大小达到规定大小时绕接。
5. TimeRotatingFileHandler--发送消息到磁盘文件,并支持在确定的时间点时绕接文件。
6. SocketHandler--发送消息给TCP/IP sockets,自3.4起支持Unix的域名sockets。
7. DatagramHandler--发送消息给UDP sockets,自3.4起支持Unix的域名sockets
8. SMTPHandler--以邮件方式发送消息
9. SysLogHandler--发送消息给Unix的守护进程,有可能是远端机器
10. NTEventLogHandler--发送消息给NT/2000/XP的event log
11. MemoryHandler--发送消息到内存缓存区,当指定的条件达到时将被清除。
12. HTTPHandler--使用GET或POST方法发送消息到HTTP服务器
13. WatchedFileHandler--观察正在使用的日志文件,当文件改变时,就关闭然后重新打开,只支持linux系统
14. QueueHandler--发送消息给一个队列,例如queue或multiprocessing这些使用queue的模块
15. NullHandler--发生错误日志时不做任何事情
原创粉丝点击