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模块的更多相关文章

  1. Python之路(第十七篇)logging模块

    一.logging模块 (一).日志相关概念 日志是一种可以追踪某些软件运行时所发生事件的方法.软件开发人员可以向他们的代码中调用日志记录相关的方法来表明发生了某些事情.一个事件可以用一个可包含可选变 ...

  2. Python日志(logging)模块,shelve,sys模块

    菜鸟学python第十七天 1.logging 模块 logging模块即日志记录模块 用途:用来记录日志 为什么要记录日志: 为了日后复查,提取有用信息 如何记录文件 直接打开文件,往里写东西 直接 ...

  3. Python Logging模块的简单使用

    前言 日志是非常重要的,最近有接触到这个,所以系统的看一下Python这个模块的用法.本文即为Logging模块的用法简介,主要参考文章为Python官方文档,链接见参考列表. 另外,Python的H ...

  4. logging 模块误用导致的内存泄露

    首先介绍下怎么发现的吧, 线上的项目日志是通过 logging 模块打到 syslog 里, 跑了一段时间后发现 syslog 的 UDP 连接超过了 8W, 没错是 8 W. 主要是 logging ...

  5. python logging模块详解[转]

    一.简单将日志打印到屏幕: import logging logging.debug('debug message') logging.info('info message') logging.war ...

  6. python logging模块

    1.logging模块提供了四个组件logger:日志类,有两个功能1)配置日志的等级,处理器handler,过滤器filterlogger.setLevel(logging.INFO)logger. ...

  7. python logging模块可能会令人困惑的地方

    python logging模块主要是python提供的通用日志系统,使用的方法其实挺简单的,这块就不多介绍.下面主要会讲到在使用python logging模块的时候,涉及到多个python文件的调 ...

  8. Python之logging模块

    一.引言 之前在写一些小程序的时候想把日志内容打到文件中,所以就自己写了一个logger.py的程序,如下: #!/usr/bin/python # -*- coding=utf-8 -*- impo ...

  9. logging模块转载博客

     转载自:http://blog.csdn.net/zyz511919766/article/details/25136485 简单将日志打印到屏幕: [python] view plain copy ...

随机推荐

  1. linux 上安装部署python

    一般在linux中使用python 需要安装pyenv 进行版本控制 因为linux6.9自带的Python是2.6的 同时很多命令都是基于2.6开发的 所以系统环境不能改 我们要开发 只能用pyen ...

  2. Android全面解析之由浅及深Handler消息机制

    前言 很高兴遇见你~ 欢迎阅读我的文章. 关于Handler的博客可谓是俯拾皆是,而这也是一个老生常谈的话题,可见的他非常基础,也非常重要.但很多的博客,却很少有从入门开始介绍,这在我一开始学习的时候 ...

  3. Java程序执行过程及内存机制

    本讲将介绍Java代码是如何一步步运行起来的,其中涉及的编译器,类加载器,字节码校验器,解释器和JIT编译器在整个过程中是发挥着怎样的作用.此外还会介绍Java程序所占用的内存是被如何管理的:堆.栈和 ...

  4. 使用tkinter打造一个小说下载器,想看什么小说,就下什么

    前言 今天教大家用户Python GUI编程--tkinter 打造一个小说下载器,想看什么小说,就下载什么小说 先看下效果图 Tkinter 是使用 python 进行窗口视窗设计的模块.Tkint ...

  5. 程序员必读的 99 本书籍 & 资源

    作为程序员,始终要保持学习,一直带着纸质书还是很不便的,因此电子书对于我们还是挺需要的.为了方便广大的小伙伴也能方便找到对应的电子书,我花费洪荒之力从各个搜索网站收集了几百本常用的电子书,找到了,我要 ...

  6. remmina 软件rdp协议链接windows失败

    remmina 1.42  链接 win10 提示失败......其他版本win还没有测试过. 忘记了在那个论坛有是说加密问题,照着改确实可以.具体原因是默认设置加密方式这一项不知道为什么不起作用,手 ...

  7. Go语言(1)——程序结构

    程序结构 基础部分仅仅列举和其他语言不一样的地方(C语言为例). 声明 Go语言有四个主要声明:var.const.type.func,类似于C语言中的变量,常量,结构体和函数. package ma ...

  8. react第十九单元(react+react-router-dom+redux综合案例1)

    第十九单元(react+react-router-dom+redux综合案例1) #课程目标 复习 综合练习 实战能力 #知识点 react react-router redux #授课思路 #案例和 ...

  9. [打基础]luogu2181对角线——计数原理

    啦啦啦我ysw又回来啦!之后大概会准备打acm,暑假尽量复习复习,因为已经快两年没碰oi了,最多也就高三noip前学弟学妹出题讲题,所以从这一篇blog开始大概会有一系列"打基础" ...

  10. 个人微信公众号搭建Python实现 -个人公众号搭建-处理消息和事件(14.3.4)

    @ 目录 1.消息处理 2.事件处理 3.返回处理 关于作者 1.消息处理 现在只处理text文本消息 没有关键字的就交给qingyunke机器人去应付,这是一个免费的对话api 从配置文件中读取关键 ...