参考:https://www.cnblogs.com/yuanchenqi/articles/5732581.html

一 (简单应用)

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

输出:

WARNING:root:warning message
ERROR:root:error message
CRITICAL:root:critical message

可见,默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET),默认的日志格式为日志级别:Logger名称:用户输出消息。

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

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='/tmp/test.log',
filemode='w') logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')

查看输出:
cat /tmp/test.log 
Mon, 05 May 2014 16:29:53 test_logging.py[line:9] DEBUG debug message
Mon, 05 May 2014 16:29:53 test_logging.py[line:10] INFO info message
Mon, 05 May 2014 16:29:53 test_logging.py[line:11] WARNING warning message
Mon, 05 May 2014 16:29:53 test_logging.py[line:12] ERROR error message
Mon, 05 May 2014 16:29:53 test_logging.py[line:13] CRITICAL critical message

可见在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对象

上述几个例子中我们了解到了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('test.log') # 再创建一个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.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')

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

(1)

Logger是一个树形层级结构,输出信息之前都要获得一个Logger(如果没有显示的获取则自动创建并使用root Logger,如第一个例子所示)。
      logger = logging.getLogger()返回一个默认的Logger也即root Logger,并应用默认的日志级别、Handler和Formatter设置。
当然也可以通过Logger.setLevel(lel)指定最低的日志级别,可用的日志级别有logging.DEBUG、logging.INFO、logging.WARNING、logging.ERROR、logging.CRITICAL。
      Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical()输出不同级别的日志,只有日志等级大于或等于设置的日志级别的日志才会被输出

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')

只输出了
2014-05-06 12:54:43,222 - root - WARNING - logger warning message
2014-05-06 12:54:43,223 - root - ERROR - logger error message
2014-05-06 12:54:43,224 - root - CRITICAL - logger critical message
     从这个输出可以看出logger = logging.getLogger()返回的Logger名为root。这里没有用logger.setLevel(logging.Debug)显示的为logger设置日志级别,所以使用默认的日志级别WARNIING,故结果只输出了大于等于WARNIING级别的信息。

(2) 如果我们再创建两个logger对象:

##################################################
logger1 = logging.getLogger('mylogger')
logger1.setLevel(logging.DEBUG) logger2 = logging.getLogger('mylogger')
logger2.setLevel(logging.INFO) logger1.addHandler(fh)
logger1.addHandler(ch) logger2.addHandler(fh)
logger2.addHandler(ch) logger1.debug('logger1 debug message')
logger1.info('logger1 info message')
logger1.warning('logger1 warning message')
logger1.error('logger1 error message')
logger1.critical('logger1 critical message') logger2.debug('logger2 debug message')
logger2.info('logger2 info message')
logger2.warning('logger2 warning message')
logger2.error('logger2 error message')
logger2.critical('logger2 critical message')

这里有两个个问题:

<1>我们明明通过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的输出遵从了后来设置的日志级别。

<2>为什么logger1、logger2对应的每个输出分别显示两次?
       这是因为我们通过logger = logging.getLogger()显示的创建了root Logger,而logger1 = logging.getLogger('mylogger')创建了root Logger的孩子(root.)mylogger,logger2同样。而孩子,孙子,重孙……既会将消息分发给他的handler进行处理也会传递给所有的祖先Logger处理。

ok,那么现在我们把

# logger.addHandler(fh)

# logger.addHandler(ch)  注释掉,我们再来看效果:

因为我们注释了logger对象显示的位置,所以才用了默认方式,即标准输出方式。因为它的父级没有设置文件显示方式,所以在这里只打印了一次。

孩子,孙子,重孙……可逐层继承来自祖先的日志级别、Handler、Filter设置,也可以通过Logger.setLevel(lel)、Logger.addHandler(hdlr)、Logger.removeHandler(hdlr)、Logger.addFilter(filt)、Logger.removeFilter(filt)。设置自己特别的日志级别、Handler、Filter。若不设置则使用继承来的值。

<3>Filter
     限制只有满足过滤规则的日志才会输出。
     比如我们定义了filter = logging.Filter('a.b.c'),并将这个Filter添加到了一个Handler上,则使用该Handler的Logger中只有名字带          a.b.c前缀的Logger才能输出其日志。

filter = logging.Filter('mylogger')

logger.addFilter(filter)

这是只对logger这个对象进行筛选

如果想对所有的对象进行筛选,则:

filter = logging.Filter('mylogger')

fh.addFilter(filter)

ch.addFilter(filter)

      这样,所有添加fh或者ch的logger对象都会进行筛选。

												

py之logging模块的更多相关文章

  1. 解决多个py模块调用同一个python的logging模块,打印日志冲突问题

    前期对python中的logging模块进行了封装,这样自动化测试框架中的多个测试脚本(py)就可以使用同一个封装后的日志系统,这样各脚本中只需要引用一下即可,方面快捷.那么当我使用unittest框 ...

  2. Python Logging模块的简单使用

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

  3. python logging模块详解[转]

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

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

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

  5. Python之logging模块

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

  6. logging模块转载博客

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

  7. Python中的logging模块

    http://python.jobbole.com/86887/ 最近修改了项目里的logging相关功能,用到了python标准库里的logging模块,在此做一些记录.主要是从官方文档和stack ...

  8. Python中的日志管理Logging模块

    1.基本的用法 import logging logging.debug('This is debug message') logging.info('This is info message') l ...

  9. Python日志输出——logging模块

    Python日志输出——logging模块 标签: loggingpythonimportmodulelog4j 2012-03-06 00:18 31605人阅读 评论(8) 收藏 举报 分类: P ...

随机推荐

  1. Java实现 LeetCode 539 最小时间差(单位转换)

    539. 最小时间差 给定一个 24 小时制(小时:分钟)的时间列表,找出列表中任意两个时间的最小时间差并已分钟数表示. 示例 1: 输入: ["23:59","00:0 ...

  2. Java实现蓝桥杯VIP算法训练 最大获利

    试题 算法训练 最大获利 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 Chakra是一位年轻有为的企业家,最近他在进军餐饮行业.他在各地开拓市场,共买下了N个饭店.在初期的市场调 ...

  3. Java实现 LeetCode 232 用栈实现队列

    232. 用栈实现队列 使用栈实现队列的下列操作: push(x) – 将一个元素放入队列的尾部. pop() – 从队列首部移除元素. peek() – 返回队列首部的元素. empty() – 返 ...

  4. Java实现 LeetCode 14 最长公共前缀

    14. 最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower",&quo ...

  5. Java实现 LeetCode 10 正则表达式匹配

    10. 正则表达式匹配 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配. '.' 匹配任意单个字符 '*' 匹配零个或多个前面的那一个元素 所谓匹配, ...

  6. java实现 猜数字游戏

    猜数字游戏 猜数字 很多人都玩过这个游戏:甲在心中想好一个数字,乙来猜.每猜一个数字,甲必须告诉他是猜大了,猜小了,还是刚好猜中了.下列的代码模拟了这个过程.其中用户充当甲的角色,计算机充当乙的角色. ...

  7. PAT 部分A+B

    正整数​​A的“DA(为 1 位整数)部分”定义为由A中所有DA组成的新整数PA,例如:给定A=3862767,DA=6,则A的“6 部分”PA是 66,因为A中有 2 个 6. 现给定A,DA,B, ...

  8. 关于C#委托三种调用的分享

    一.同步调用 1.同步调用会按照代码顺序来执行2.同步调用会阻塞线程,如果是要调用一项繁重的工作(如大量IO操作),可能会让程序停顿很长时间,造成糟糕的用户体验,这时候异步调用就很有必要了. 举个栗子 ...

  9. leetcode之两数相加解题思路

    问题描述 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,数组中同一个元素不能使 ...

  10. PL/SQL编程急速上手

    结构化查询语言(SQL)是第四代编程语言的典型,这种命令式的语言更像一种指令,使用它,你只需要告诉计算机“做什么”,而不用告诉计算机“怎么做”.第四代编程语言普遍具有简单.易学.能更快的投入生产等优点 ...