Python 日志组件学习(一)

本文详细介绍了Python标准库中的logging模块、Twisted框架中的twisted.python.log模块及twisted.logger模块的工作原理与使用方法,包括如何自定义Handler和Observer。

Python log组件

主要 对以下python日志组件分析说明.
[TOC]

  • logging
  • twisted.python.log
  • twisted.logger

    python 日志的官方说明文档比较简单,一般使用没什么问题,不过了解一些基本的原理,可能在一些复杂的项目里使用起来比较方便一些

logging

logging 是python 标准的日志组件

使用:

import logging  
logging.baseConfig()
tag = 'test'  # 标签
mylogger = logging.getLogger(tag) # 创建一个Logger类对象
mylogger.info('This is a test msg') # 调用日志打印

原理:

logging.baseConfig() 设置配置参数,默认情况下会向root添加一个StreamHandler对象(一会再说root和Handler),
并且这个StreamHandler对象的stream属性为sys.stderr

当调用mylogger.info时做了哪些事情呢?不管是mylogger.info, mylogger.error,还是mylogger.log方法,都是调用了内部的_log方法,却别在于,日志的级别不同,当级别大于等于在logging.baseConfig()设置打印的级别时,_log方法将会被调用。

下面是重点了,以mylogger为例子(它是一个Logger对象),它有一个属性Handlers 列表,默认情况下是是个空列表,调用_log方法时,会触发Handlers 列表中的所有handle ,调用完这些handle 之后,还会去遍历mylogger.parent的Handlers (可以通过设置Logger的propagate=False,来禁止parent的handle被调用),默认情况下parten = root ,root 实际上也是一个Logger实例。

比如一个默认的StreamHandler对象s_handle,当s_handle被触发的时候,s_handle.stream.write(xxx)将被调用,前面说了,默认这个stream = sys.stderr, 意思就是这个handle会将信息打印到屏幕上。

如果你想让你的日志对象,做一些你希望的操作,可以自定义handle,将handle添加到mylogger的Handlers列表中,
在下面的例子中,添加了一个fluent的handle到mylogger(fluent可以将日志接到Kibana网页中显示)


line_format = {
        'file_name': '%(module)s',
        'log_level': '%(levelname)s',
        'line': '%(lineno)d',
        'server': '测试区'
    }

    l = logging.getLogger(log_name)
    h = handler.FluentHandler(log_name, host='192.168.7.99', port=54224) # 创建一个fluent handle
    formatter = handler.FluentRecordFormatter(line_format) # 创建fluent handle信息格式对象
    h.setFormatter(formatter) # 将信息格式对象添加到handle
    l.setLevel(logging.INFO)
    l.addHandler(h) # 将handle 添加到l的Handlers列表里

总结:

python logging组件核心就是调用handle

twisted.python.log

这是twisted组件里的log模块

使用:

简单的用法如下面的例子

from twisted.python import log
log.msg('This is a test msg') # log普通信息
# 或者
log.err('This is a test err') # log错误级别的信息

原理:

(log.err 实际上就是将日志级别定义成ERROR后调用log.msg)

twisted组件里的log模块主要有个LogPublisher(分发者),姑且就叫它分发器吧。

当log.msg被调用的时候,会抛出一个log事件(实际上就是定义一个eventDict事件字典)给LogPublisher,接着LogPublisher会将这个log事件发送给所有observer(观察者)

LogPublisher(分发器)的_publishPublisher属性是一个绑定了ILogObserver接口类的类(也就是一个观察者)(听着有点拗口…),ILogObserver里面暴露了call方法,log.msg将log事件抛给 LogPublisher (分发器),在由分发器的 _publishPublisher属性的call方法里遍历了所有其他的observer, 是不是感觉似曾相识,twisted python log里的observer 和 python 标准库log的handle有异曲同工之处啊。

下面的例子,自定义了一个observer,并将这个observer添加到 LogPublisher 的Observers列表里

from twisted.python import log

class loogoo():
    # 自定义观察者
    implements(log.ILogObserver)

    def __init__(self, path):
        self.file = file(path, "a+")

    def __call__(self, event):
        text = formatEvent(event)
        self.file.write(text + '\n')
        self.file.flush()

if __name__ == '__main__':
    log.addObserver(loogoo('app.log')) # 添加观察者
    log.startLogging(sys.stdout)

我感觉这里不用log.startLogging(sys.stdout)也是可以的, 那么log.startLogging(sys.stdout)有什么用呢?
我感觉主要做了2件事情:
第一,以sys.stdout作为file创建了一个observer加入到分发器,那么log日志就会被打印到屏幕上。
第二,log.startLogging(sys.stdout) 实际等于 log.startLogging(sys.stdout, setStdout=1),setStdout参数为真的情况下,sys.stdout 和 sys.stderr 会被重定向为 twisted.logger._io.LoggingFile对象,这个对象的write方法里面正是调用了log.msg,这就意味着,之后有调用到sys标准输出和标准错误,这个信息都会被LogPublisher(分发者)捕获到。
另外如果setStdout=0 或者False, sys.stdout 和 sys.stderr都不会被重定向
综合上面几点,可以看出twisted.python.log 模块仅仅只是能捕获自身抛出的log事件,如果要捕获 python logging 抛出的log信息, 那么log.startLogging(sys.stdout)就可以,因为默认情况下,python logging parent有执行sys.stderr的handle

twisted.logger

现在去查看twisted.python.log的文档就可以发现There is now a new logging system in Twisted ,正是twisted.logger,这两者其实没有什么却别,twisted.python.log是在twisted.logger的基础上又封装了一层

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值