原文地址:http://www.cnblogs.com/sislcb/archive/2008/11/25/1340627.html

从Python2.3版本中开始引入的logging模块为应用提供了灵活的日志系统。

logging的行为依靠调用 Logger 类的方法来实现,实例一般叫做logger。每个实例都拥有自己的名字,并且可以通过点来分割具备层次的名字。例如,一个logger叫做”scan”是一个叫做”scan.text”的logger的顶层,当然也包括”scan.html”和”scan.pdf”。logger的名字指示了他属于应用程序的哪个位置。

日志信息也拥有级别指定其重要程度。缺省提供的级别包括DEBUG,INFO,WARNING,ERROR,CRITICAL(严重)。为了方便,你可以调用特定的方法来指定日志的重要性,对应的方法为 debug() , info() , warning() , error() , critical() 。你也不必拘泥于这些级别,你可以使用更为通用的方法 log() 并且手动指定其级别。

日志级别对应值如下表所示。了解这些有助于你定义自己的日志级别的相对关系。如果你定义的级别与已有的数值相同,则原有的级别会被覆盖。

级别 数值
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0

日志级别也可以在指定logger时定义,可以在开发时装入和存储配置。当调用logger的日志方法时,logger对比日志级别和自己的被指定的级别。如果本身的级别高于调用方法的级别,则不会记录这个日志信息。这是一个方便的方法用于忽略过多细节的日志。

日志信息会被编码为 LogRecord 类,当logger决定记录一个事件时,就会为日志信息创建一个LogRecord实例。

日志信息会被发布(dispatch)机制通过handler来发布出去,这些handler继承自 Handler 类。Handler负责把日志信息(LogRecord的实例)发布到对应的位置供处理这些信息。Handler传递LogRecord实例并指定特定目标。每个logger都可以拥有0个或多个handler,通过 addHandler() 方法添加。除了handler与logger的组合之外,所有的handler还会被所组合的祖先logger所调用来发布信息。

有如logger,handler也可以有自己的级别过滤器,用于过滤日志级别。如果一个handler决定发布一个事件,可以调用 emit() 来发送信息到目的。大多数用户继承的Handler的子类需要重载这个emit()方法。

除了基本的Handler类,比较有用的子类如:

  1. StreamHandler实例发送错误到流(类似文件的对象)。
  2. FileHandler实例发送错误到磁盘文件。
  3. BaseRotatingHandler是所有轮徇日志的基类,不能直接使用。但是可以使用RotatingFileHandler和TimeRotatingFileHandler。
  4. RotatingFileHandler实例发送信息到磁盘文件,并且限制最大的日志文件大小,并适时轮徇。
  5. TimeRotatingFileHandler实例发送错误信息到磁盘,并在适当的事件间隔进行轮徇。
  6. SocketHandler实例发送日志到TCP/IP socket。
  7. DatagramHandler实例发送错误信息通过UDP协议。
  8. SMTPHandler实例发送错误信息到特定的email地址。
  9. SysLogHandler实例发送日志到UNIX syslog服务,并支持远程syslog服务。
  10. NTEventLogHandler实例发送日志到WindowsNT/2000/XP事件日志。
  11. MemoryHandler实例发送日志到内存中的缓冲区,并在达到特定条件时清空。
  12. HTTPHandler实例发送错误信息到HTTP服务器,通过GET或POST方法。

StreamHandler和FileHandler类都是在核心logging模块中定义的。其他handler定义在各个子模块中,叫做logging.handlers。当然还有一个logging.config模块提供了配置功能。

日志信息在输出之前会经过 Formatter 类的格式化。他们在最开始使用%操作符来设置。

批量格式化信息,需要 BufferingFormatter 类。除了格式化字符串之外,它还会在输出信息之前加上其他信息。

当基于logger和handler的级别过滤器仍然不够时,可以使用 Filter 类的实例来添加到logger和handler实例中,通过他们的 addFilter() 方法。当决定输出日志之前,logger和handler会询问过滤器,如果过滤器返回False,则不会显示这条日志。

最简单的过滤器功能用于指定日志的名字。如果使用了这个过滤器,则发送到命名logger和其子logger的日志将会通过,其他的会被丢弃。

除了上面所描述的,还有很多模块级别的函数。如下:

getLogger([name])

返回一个logger,可以指定名字,如果没有指定名字则返回根logger。指定的名字典型的为以点分隔的分层次的名字。选择一个恰当的名字,让别人知道,谁在输出日志。所有使用相同名字调用这个函数都会返回相同的logger实例。这意味着logger实例不需要在应用中到处传递。

getLoggerClass()

返回一个标准的Logger类,或者上次传递到 setLoggerClass() 的类。这个函数用于定义一个新的日志类,但是之前的代码不会受到影响。例如:

class MyLogger(logging.getLoggerClass()):
#重载一些行为

debug(msg[,*args[,**kwargs]])

记录一个DEBUG级别的日志信息到根logger。 msg 参数就是用于输出的日志, args 参数是用于填入msg字符串的参数,当然kwargs也是差不多的角色。这说明msg可以是一个包含%d、%s等等的待格式化字符串。

在kwargs中有2个参数是必须的: exc_info 如果不为False,则异常产生的信息也会被记录;如果提供了一个异常tuple(以 sys.exc_info() 格式),则会使用它;否则会调用 sys.exc_info() 来获取异常信息。

另外一个参数为 extra 用于传递一个字典表示 LogRecord 中的 __dict__ 信息,可以加入用户自定义属性。这些传递的参数可以随你喜欢的。例如可能需要传递的:

FORMAT="%(asctime)-15s %(clientip)s %(user)-8s %(message)s"
logging.basicConfig(format=FORMAT)
dict={'clientip':'192.168.1.1','user':'fbloggs'}
logging.warning("Protocol problem: %s","connection reset",extra=d)

将会有如下的显示:

2006-02-08 22:20:02,165 192.168.1.1 fbloggs Protocol problem: connection reset

extra字典中的键不会与已有的键相冲突,具体可以参考Formatter的文档中关于使用字典的部分。

在选择字典中的键名时,必须小心一些情况。上面的例子中,已经在待格式化字符串中有’clientip’和’user’了,这时如果没有传递这两个键,则不会输出日志,因为出现了异常了。这种情况时,你必须要传递这2个键。

出于这种复杂性,这种功能往往用在很特殊的地方,比如多线程服务器,或关心多种信息的上下文环境,例如远程IP和登录用户。在这些情况中,需要先指定Formatter实例。 extra 参数从2.5版本开始加入。

info(msg[,*args[,**kwargs]])

记录INFO级别的日志信息,其他参数同debug()。

warning(msg[,*args[,**kwargs]])

记录WARNING级别的日志信息,其他参数同debug()。

error(msg[,*args[,**kwargs]])

记录ERROR级别的日志信息,其他参数同debug()。

critical(msg[,*args[,**kwargs]])

记录CRITICAL级别的日志信息,其他参数同debug()。

exception(msg[,*args])

记录ERROR级别的日志信息,其他参数同debug()。一般用在异常处理中。

log(level,msg[,*args[,**kwargs]])

记录level级别的日志信息,其他参数同debug()。

disable(lvl)

提供一个在logger中禁用某个级别日志的方法,用于应用临时切换可显示的日志。

addLevelName(lvl,levelName)

给级别lvl指定一个名字levelName到内部字典。以后用于映射数字的级别到特定的名字,供给Formatter用来格式化字符串。也可以用于定义自己的级别。这里也是唯一可以注册级别用的地方,级别必须是数字,并且在按照一定的排序要求。

getLevelName(lvl)

返回lvl级别的文字说明。如果级别是CRITICAL、ERROR、WARNING、INFO、DEBUG中的某一个,也会返回对应的名字。如果你自己通过addLevelName()自定义过级别,那么也会返回对应的名字。如果对应级别不存在,则返回 “Level %s”%lvl 这个字符串。

makeLogRecord(attrdict)

创建并返回一个LogRecord实例,并使用attrdict赋值过。这个函数用于把一个LogRecord给pickle过后通过socket发送,并方便接收方重组这个信息。

basicConfig([**kwargs])

对日志系统进行基本配置,使用缺省的StreamHandler和Formatter并添加根logger。一些函数如debug()、info()、warning()、error()、critical()会自动使用basicConfig()配置好的根logger进行日志输出。在2.4版之前,basicConfig()不接受字典参数。

如下是支持的字典参数:

格式 描述
filename 指定FileHandler的文件名,而不是StreamHandler
filemode 打开文件的模式,同open函数中的同名参数,默认为’a’
format 输出格式字符串
datefmt 日期格式
level 设置根logger的日志级别
stream 指定StreamHandler。这个参数与filename冲突,忽略stream

shutdown()

告知日志系统准备关闭日志并将所有信息写入磁盘。

setLoggerClass(klass)

告知日志系统使用类klass作为示例的Logger类。这个类应该定义 __init__() 方法并接受一个参数表示名字,而且 __init__() 方法应该在内部调用Logger.__init__() 方法。这个函数一般在应用自定义Logger的行为时使用。

 #coding: GB2312

 def initlog():
import logging # 生成一个日志对象
logger = logging.getLogger()
# 生成一个Handler。logging支持许多Handler,
# 象FileHandler, SocketHandler, SMTPHandler等,我由于要写
# 文件就使用了FileHandler。
# logfile是一个全局变量,它就是一个文件名,如:'crawl.log'
logfile = 'test.log'
hdlr = logging.FileHandler('sendlog.txt')
# 成一个格式器,用于规范日志的输出格式。如果没有这行代码,那么缺省的
# 格式就是:"%(message)s"。也就是写日志时,信息是什么日志中就是什么,
# 没有日期,没有信息级别等信息。logging支持许多种替换值,详细请看
# Formatter的文档说明。这里有三项:时间,信息级别,日志信息
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
# 将格式器设置到处理器上
hdlr.setFormatter(formatter)
# 将处理器加到日志对象上
logger.addHandler(hdlr)
# 设置日志信息输出的级别。logging提供多种级别的日志信息,如:NOTSET,
# DEBUG, INFO, WARNING, ERROR, CRITICAL等。每个级别都对应一个数值。
# 如果不执行此句,缺省为30(WARNING)。可以执行:logging.getLevelName
# (logger.getEffectiveLevel())来查看缺省的日志级别。日志对象对于不同
# 的级别信息提供不同的函数进行输出,如:info(), error(), debug()等。当
# 写入日志时,小于指定级别的信息将被忽略。因此为了输出想要的日志级别一定
# 要设置好此参数。这里我设为NOTSET(值为0),也就是想输出所有信息
logger.setLevel(logging.NOTSET)
return logger
logging=initlog()
logging.info('注册')

通过以上例子个人总结:

初始化一个写文件的log对象的步骤:

1.先生成一个logger 对象:

logger = logging.getLogger()

2.生成一个处理器Hander:

hdlr = logging.FileHandler( file )

file: 可以是带路径的全文件路径,如:“D://logs//test.log”

3.生存格式器制定输出日志格式:

formatrer = logging.Formatter('%(asctime)s %(levelname)s %(message)s')

格式字符:

4.将格式器绑定到处理器Hander上:

hdlr.setFormatter(formatter)

5.将处理器Hander添加到log对象上

logger.addHandler(hdlr)

6.根据实际情况设置日志级别

logger.setLevel(logging.NOTSET)

若想支持的级别多点,最好设置的级别低点。

python logging模块+ 个人总结的更多相关文章

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

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

  2. python logging模块使用

    近来再弄一个小项目,已经到收尾阶段了.希望加入写log机制来增加程序出错后的判断分析.尝试使用了python logging模块. #-*- coding:utf-8 -*- import loggi ...

  3. 读懂掌握 Python logging 模块源码 (附带一些 example)

    搜了一下自己的 Blog 一直缺乏一篇 Python logging 模块的深度使用的文章.其实这个模块非常常用,也有非常多的滥用.所以看看源码来详细记录一篇属于 logging 模块的文章. 整个 ...

  4. (转)python logging模块

    python logging模块 原文:http://www.cnblogs.com/dahu-daqing/p/7040764.html 1 logging模块简介 logging模块是Python ...

  5. Python logging 模块学习

    logging example Level When it's used Numeric value DEBUG Detailed information, typically of interest ...

  6. python logging—模块

    python logging模块 python logging提供了标准的日志接口,python logging日志分为5个等级: debug(), info(), warning(), error( ...

  7. Python logging模块无法正常输出日志

    废话少说,先上代码 File:logger.conf [formatters] keys=default [formatter_default] format=%(asctime)s - %(name ...

  8. 0x03 Python logging模块之Formatter格式

    目录 logging模块之Formatter格式 Formater对象 日志输出格式化字符串 LogRecoder对象 时间格式化字符串 logging模块之Formatter格式 在记录日志是,日志 ...

  9. 0x01 Python logging模块

    目录 Python logging 模块 前言 logging模块提供的特性 logging模块的设计过程 logger的继承 logger在逻辑上的继承结构 logging.basicConfig( ...

  10. Python Logging模块的简单使用

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

随机推荐

  1. HDU5661 Claris and XOR

    我们求二进制是怎么求的呢:先看看二进制的每一位代表多大:.......32 16 8 4 2 1 假如n=10, ..... 32>n ,不要. 16>n,不要. 8<=n,要,然后 ...

  2. WPF之DataGrid应用

    前几天打算尝试下DataGrid的用法,起初以为应该很简单,可后来被各种使用方法和功能实现所折磨.网络上的解决方法太多,但也太杂.没法子,我只好硬着头皮阅览各种文献资料,然后不断的去尝试,总算小有成果 ...

  3. 组件 layui 常用控件下拉框的应用

    下拉框的显示样式: 针对下拉框的绑定等操作时,在最后务必调用一次 form.render(); 1.基本定义: <div class="layui-form-item"> ...

  4. android Intent机制详解

    http://www.oschina.net/question/565065_67909 http://www.cnblogs.com/hummersofdie/archive/2011/02/12/ ...

  5. HTML之事件处理程序

    HTML事件 <body> <input type="button" value="按钮1" id="but1" oncl ...

  6. JavaScript注释之HTML注释(<!-- & //-->)

    JavaScript中支持HTML注释 //用法 <script language="javascript"> <!-- alert("我是注释内的JS ...

  7. [转载]Vector用法(C++ Primer中文版)

    转自:http://blog.sciencenet.cn/blog-261330-551086.html vector 是同一种类型的对象的集合,每个对象都有一个对应的整数索引值.和 string 对 ...

  8. python-opencv aplpha混合

    import cv2 import os import numpy as np print os.listdir(os.getcwd()) img = cv2.imread('building.jpg ...

  9. sql里的null和空的区别

    null表示为未知,未定义: 空表示为空白,或者0: sql查询,排序时null在''的前面: 定义字段为not null,写为空可以写入: null不可以用来比较,只能用is null判断:

  10. nginx + tomcat + redis 部署项目,解决session共享问题。

    最近自己搭了一套nginx的环境,集群部署了公司的一个项目,中间解决了session共享的问题.记录如下,以备日后查看. 1.环境 windows10 家庭中文版,jdk 7, tomcat 7.0. ...