(十七)logging模块
logging模块是Python内置的标准模块,主要用于输出运行日志。
简单应用
import logging
logging.debug('+++debug+++')
logging.info('+++info+++')
logging.warning('+++warning+++')
logging.error('+++error+++')
logging.critical('+++critical+++')
结果:
WARNING:root:+++warning+++
ERROR:root:+++error+++
CRITICAL:root:+++critical+++
可见,默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET),默认的日志格式为 日志级别:Logger名称:用户输出消息
灵活配置日志级别,日志格式,输出位置
import logging
logging.basicConfig(level=logging.DEBUG, #级别为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') #默认是a追加,w是写入 logging.debug('+++debug+++')
logging.info('+++info+++')
logging.warning('+++warning+++')
logging.error('+++error+++')
logging.critical('+++critical+++')
test.log内容: Tue, 15 Jan 2019 20:20:06 logging_lesson.py [line:9] DEBUG +++debug+++
Tue, 15 Jan 2019 20:20:06 logging_lesson.py [line:10] INFO +++info+++
Tue, 15 Jan 2019 20:20:06 logging_lesson.py [line:11] WARNING +++warning+++
Tue, 15 Jan 2019 20:20:06 logging_lesson.py [line:12] ERROR +++error+++
Tue, 15 Jan 2019 20:20:06 logging_lesson.py [line:13] CRITICAL +++critical+++
可见在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
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参数会被忽略。
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对象
import logging
logger = logging.getLogger() #返回一个logger对象 fh = logging.FileHandler('test2_log') #创建一个handler,用于写入日志文件
ch = logging.StreamHandler() #再创建一个handler,用于输出到控制台 fm = logging.Formatter('%(asctime)s %(message)s') #创建一个格式,将用于上面的两个handler fh .setFormatter(fm) #两个handler设定格式
ch.setFormatter(fm) logger.addHandler(fh) #两个handler都添加进logger对象
logger.addHandler(ch) logger.setLevel('DEBUG') #设置logger的日志级别 logger.debug('+++debug+++') #正式调用logger对象打印日志
logger.info('+++info+++')
logger.warning('+++warning+++')
logger.error('+++error+++')
logger.critical('+++critical+++')
结果:控制台输出和test2_log文件中的内容都是:
2019-01-15 23:29:18,465 +++debug+++
2019-01-15 23:29:18,465 +++info+++
2019-01-15 23:29:18,465 +++warning+++
2019-01-15 23:29:18,465 +++error+++
2019-01-15 23:29:18,465 +++critical+++
如上图,fh和ch作为两个handler对象(一个负责写入文件,一个负责控制台输出),都"吃"掉了fm这个格式对象,又都被最后负责打印日志的logger对象"吃"掉。
使用logger对象是我们常用的方式,Logger是一个树形层级结构, logger = logging.getLogger()返回一个默认的Logger也即root Logger,并应用默认的日志级别、Handler和Formatter设置。
当然也可以通过Logger.setLevel(lel)指定最低的日志级别,可用的日志级别有logging.DEBUG、logging.INFO、logging.WARNING、logging.ERROR、logging.CRITICAL。
但是有两个注意点:
1.只要logging.getLogger(name)中名称参数name相同则返回的Logger实例就是同一个,且仅有一个
import logging
logger1 = logging.getLogger('mylogger')
logger1.setLevel(logging.DEBUG) logger2 = logging.getLogger('mylogger')
logger2.setLevel(logging.INFO) fh = logging.FileHandler('test1_log')
ch = logging.StreamHandler() logger1.addHandler(fh)
logger1.addHandler(ch)
logger2.addHandler(fh)
logger2.addHandler(ch) logger1.debug('logger1+++debug+++')
logger1.info('logger1+++info+++')
logger1.warning('logger1+++warning+++')
logger1.error('logger1+++error+++')
logger1.critical('logger1+++critical+++')
logger2.debug('logger2+++debug+++')
logger2.info('logger2+++info+++')
logger2.warning('logger2+++warning+++')
logger2.error('logger2+++error+++')
logger2.critical('logger2+++critical+++')
结果:控制台输出和test1_log文件中的内容都是:
logger1+++info+++ #logger1虽然设置了日志级别为DEBUG,但遵从logger2设置的日志级别INFO,因为两者对应的是同一个Logger实例
logger1+++warning+++
logger1+++error+++
logger1+++critical+++
logger2+++info+++
logger2+++warning+++
logger2+++error+++
logger2+++critical+++
logger1.setLevel(logging.DEBUG)将logger1的日志级别设置为了DEBUG,为何显示的时候没有显示出DEBUG级别的日志信息,而是从INFO级别的日志开始显示呢?
原来logger1和logger2对应的是同一个Logger实例,只要logging.getLogger(name)中名称参数name相同则返回的Logger实例就是同一个,且仅有一个,就是说name与Logger实例一一对应。在logger2实例中通过logger2.setLevel(logging.INFO)设置mylogger的日志级别为logging.INFO,所以最后logger1的输出遵从了后来设置的日志级别。
所以,创建Logger时,如果是需要两个实例对象,就要在logging.getLogger(name)中把name参数区分开。
2."子实例"的handler进行处理时,也会传递给所有的"父实例"Logger处理,所以子实例的处理会被执行多次。
import logging
logger = logging.getLogger() logger2 = logging.getLogger('mylogger2')
logger2.setLevel(logging.INFO) ch = logging.StreamHandler() logger.addHandler(ch)
logger2.addHandler(ch) logger.debug('logger+++debug+++')
logger.info('logger+++info+++')
logger.warning('logger+++warning+++')
logger.error('logger+++error+++')
logger.critical('logger+++critical+++')
logger2.debug('logger2+++debug+++')
logger2.info('logger2+++info+++')
logger2.warning('logger2+++warning+++')
logger2.error('logger2+++error+++')
logger2.critical('logger2+++critical+++')
结果:
logger+++warning+++
logger+++error+++
logger+++critical+++
logger2+++info+++ #logger2执行了两次
logger2+++info+++
logger2+++warning+++
logger2+++warning+++
logger2+++error+++
logger2+++error+++
logger2+++critical+++
logger2+++critical+++
通过logger = logging.getLogger()创建了root Logger,而logger2 = logging.getLogger('mylogger2')创建了root Logger的“子实例”logger2。而孩子,孙子,重孙……的handler进行处理时,也会传递给所有祖先的Logger处理,所以logger2被执行了两边。
也就是说,子实例工作的时候会依次去找他的父辈(树结构,可能有好几层父辈)有没有在工作,如果有一个父辈在工作,子实例就多工作一次。
上述例子中,如果把logger.addHandler(ch)注释掉,logger2就只执行一遍。
(十七)logging模块的更多相关文章
- Python之路(第十七篇)logging模块
一.logging模块 (一).日志相关概念 日志是一种可以追踪某些软件运行时所发生事件的方法.软件开发人员可以向他们的代码中调用日志记录相关的方法来表明发生了某些事情.一个事件可以用一个可包含可选变 ...
- Python日志(logging)模块,shelve,sys模块
菜鸟学python第十七天 1.logging 模块 logging模块即日志记录模块 用途:用来记录日志 为什么要记录日志: 为了日后复查,提取有用信息 如何记录文件 直接打开文件,往里写东西 直接 ...
- Python Logging模块的简单使用
前言 日志是非常重要的,最近有接触到这个,所以系统的看一下Python这个模块的用法.本文即为Logging模块的用法简介,主要参考文章为Python官方文档,链接见参考列表. 另外,Python的H ...
- logging 模块误用导致的内存泄露
首先介绍下怎么发现的吧, 线上的项目日志是通过 logging 模块打到 syslog 里, 跑了一段时间后发现 syslog 的 UDP 连接超过了 8W, 没错是 8 W. 主要是 logging ...
- python logging模块详解[转]
一.简单将日志打印到屏幕: import logging logging.debug('debug message') logging.info('info message') logging.war ...
- python logging模块
1.logging模块提供了四个组件logger:日志类,有两个功能1)配置日志的等级,处理器handler,过滤器filterlogger.setLevel(logging.INFO)logger. ...
- python logging模块可能会令人困惑的地方
python logging模块主要是python提供的通用日志系统,使用的方法其实挺简单的,这块就不多介绍.下面主要会讲到在使用python logging模块的时候,涉及到多个python文件的调 ...
- Python之logging模块
一.引言 之前在写一些小程序的时候想把日志内容打到文件中,所以就自己写了一个logger.py的程序,如下: #!/usr/bin/python # -*- coding=utf-8 -*- impo ...
- logging模块转载博客
转载自:http://blog.csdn.net/zyz511919766/article/details/25136485 简单将日志打印到屏幕: [python] view plain copy ...
随机推荐
- sql 执行语句函数
# sql 语句执行函数 def get_access(request): uid=request cursor=connection.cursor() cursor.execute("se ...
- Goldengate搭建
OGG进程 捕获进程(源端):捕获online redo log或者archived log中增量事务日志 传输进程(源端):把目标端落地的trail文件通过配置的路由信息传输到目标端 网络传输:tc ...
- Mycat配置分库分表(垂直分库、水平分表)、全局序列
1. Mycat相关文章 Linux安装Mycat1.6.7.4并实现Mysql数据库读写分离简单配置 Linux安装Mysql8.0.20并配置主从复制(一主一从,双主双从) Docke ...
- 迭代 可迭代对象 迭代器的bj
1.迭代的概念 迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果.每一次对过程的重复称为一次"迭代",而每一次迭代得到的结果会作为下一次迭代的初始值. 2.可迭代对象 ...
- 2020年下征文+没有计算机经验的宝妈也可以轻松领证一次过关啦 nice !相信努力总会收获
2020年下征文+没有计算机经验的宝妈也可以轻松领证http://www.1634.com.cn/ruankao/forum.php?mod=viewthread&tid=5363&f ...
- Python学习之多项式回归
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 线性回归的改进版本中的多项式回归.如果您知道线性回归,那么对您来说很简单.如果没有,我将在本文中解释 ...
- (六)、mv-一个具备更改文件名和移动文件的命令
一.mv的命令格式和作用 既可以在不同目录之间移动文件和目录,也可以在同一目录下对文件或者目录重命名,如果目标文件已经存在,则可覆盖他,若 目标文件或者目录不存在,则创建他:移动的dst必须为目录 命 ...
- js--数组的reduce()方法的使用介绍
前言 阅读文章之前先来考虑一个问题,如何去实现迭代一个数组,并且把它累加到一个值中?首先能够想到的是设置一个初始值,然后通过循环遍历这个数组,将数组中的值一项一项累加起来,然后返回这个设置的值就是最终 ...
- List集合转JSONObject
以前写代码喜欢用Map拼接返回去给前端,这样得到的也是一个标准的JSON,今天先不说Map的优缺点,我们就来说说JSONObject的使用,我用的是阿里的fastjson,先上代码,当我们需要嵌套代码 ...
- 《深入理解 Java 虚拟机》读书笔记
第二章 Java 内存区域与内存溢出溢出 程序计数器 程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器.字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的 ...