当前位置:编程学习 > 网站相关 >>

异步写日志

   为什么会想到异步写日志?
附件中下载代码:
      假设有以下函数
 
Python代码 
def myfunc(): 
     logging.info('log something ....') 
     # 
     #do something 
     # 
     logging.info('log something agein') 
     return 2 
 
      这个函数在 return 2 之前记录了2次日志。并且必须要等这两条logging写入硬盘中之后才return 2
现在遇到的一个情况就是这个函数返回之前打印了大量了日志,那就加大了调用函数的返回时间。
      想在不改变日志量的情况下,让这个函数执行返回的更加快。logging模块是使用纯python代码来实现的,写文件的效率并不高。
如果能用c或者c++重写一个logging模块,那就更好了,哈哈,但目前没这个能力拿c/c++重写。所以就想到了另外个异步开一个线程来记录日志的办法
 
    这里另外写了个日志模块 取名字叫logging2

Python代码 
<span style="font-size: small;">def myfunc(): 
     #这里改用了另外写的logging2模块 
     logging2.info('log something ....') 
     # 
     #do something 
     # 
      #这里改用了另外写的logging2模块 
     logging2.info('log something agein') 
     return 2</span> 

     logging2模块主要使用到了内置模块Queue 和 threading
logging2.info 将日志信息写如Queue中,然后另外一个线程不断的从Queue中取出日志,最终打印到硬盘中。

      logging2实际上是操作Queue,也就是与内存在进行交互的。
而logging是与硬盘来进行交互的。所以对与函数myfunc的调用来说,logging2要比logging快。这也就达到了我的目的。
 
     至于logging2使用另外一个线程来对硬盘写日志,需要的增加的开销就是:所在进程多一个线程就占用多一些内存,还有cpu占用率会多一些。

附件中下载代码:
代码例子:

example.py
Python代码 
#coding=gbk 
import sys 
import os 
import time 
import threading 
#对logging模块中logger进行的一些封装,实现按照日志按照每天一个文件 或 指定每个日志文件多大尺寸 
import LogUtil 
 
_APP_ID_ = 'logging2_test' 
############################################################ 
if __name__ == '__main__': 
    import logging2     #现在就导入logging2文件 
    LogUtil.addTimedRotatingFileHandler( 
        '%s.log' % ( _APP_ID_), 
        logLevel = 'DEBUG', 
    ) 
    #注意 
    logging2.init()             #需要多加上这一步, 只需要初始化一次  
 
    while 1: 
        time.sleep(3)  
        logging2.debug('ddd')   #现在就来使用logging2来异步记录日志 
        logging2.error('testerror') 
        logging2.info('testerror') 
        logging2.warning('testerror') 
        print threading.enumerate() 
        print 'press ctrl_c to exit' 
</span> 
 
logging2.py
Python代码 
#coding=gbk 
import threading 
from Queue import Queue 
 
import logging as log_my 
 
class logging2(threading.Thread): 
    A_Queue = Queue()     #用来存放日志的队列 
 
    def __init__(self): 
        threading.Thread.__init__(self)     #初始化父类的构造函数 
        self.name = 'logging2' 
 
    def run(self): 
        while 1: 
            data = logging2.A_Queue.get() 
            print 'datafromqueue',data 
            loglevel = data.keys()[0] 
            content = data.values()[0] 
            getattr(log_my,loglevel)(content) 
     
def info(content): 
    logging2.A_Queue.put({'info':content}) 
 
def error(content): 
    logging2.A_Queue.put({'error':content}) 
 
def debug(content): 
    logging2.A_Queue.put({'debug':content}) 
 
def warning(content): 
    logging2.A_Queue.put({'warning':content}) 
 
def init(): 
    '''''
        开启写日志的线程
    ''' 
    cc = logging2() 
    cc.setDaemon(True) 
    cc.start()

补充:Web开发 , Python ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,