Python的logging模块的使用及思考:服务器程序把每天的log写入到当天的log文件中

需求:

一个Python服务器程序,可能会连续运行几个月,现在需要把每天产生的log信息写入到当天的文件中,即每天产生一个log文件。

使用logging模块编写程序,第一个版本如下:

import logging
import time

class LogSingleton(object):

    @classmethod
    def get_logger_v1(cls):
        """
        获取一个最新设置的logger对象,使用当前时间(年-月-日)作为文件名
        :return:
        """
        logger = logging.getLogger()
        logger.setLevel(level=logging.INFO)
        handler = logging.FileHandler('%s_log.txt' % time.strftime("%Y-%m-%d"), mode='a')
        handler.setLevel(logging.INFO)
        formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
        handler.setFormatter(formatter)
        for h in logger.handlers:
            logger.removeHandler(h) # 移除其他所有的handler
        logger.addHandler(handler) # 设置新的handler
        return logger


if __name__ == '__main__':
    logger = LogSingleton.get_logger_v1()
    logger.info('xxx')

需要说明的是,logging.getLogger()是一个单例函数,当getLogger不传参数或者传入同一个字符串时,获得的log对象是同一个对象,可以通过id()函数验证。

上述代码中每次调用get_logger_v1()就会更新log对象的handler,已达到更新log文件名的目的,当被设置了新的log文件名后,logging模块会帮我们创建这个文件(前提是其路径无误),后续的log信息就会写入到这个最新handler指定的log文件中。

 

关于性能的思考

如果程序中调用的地方比较多,那我们不得不考虑他的运行性能好不好。优化的基本思路是判断当前的handler中的文件名是否是当天的,如果是,直接返回;如果不是,再设置一个新的handler返回。

下面是优化后版本:

import logging
import time
from pathlib import Path

class LogSingleton(object):

    @classmethod
    def get_logger_v2(cls):
        """
        获取一个最新设置的logger对象,使用当前时间(年-月-日)作为文件名
        :return:
        """
        logger = logging.getLogger()
        logger.setLevel(level=logging.INFO)
        if logger.hasHandlers():
            if '%s_log.txt' % time.strftime("%Y-%m-%d") == Path(logger.handlers[0].baseFilename).name:
                return logger
        handler = logging.FileHandler('%s_log.txt' % time.strftime("%Y-%m-%d"), mode='a')
        handler.setLevel(logging.INFO)
        formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
        handler.setFormatter(formatter)
        for h in logger.handlers:
            logger.removeHandler(h) # 移除其他所有的handler,如果不移除之前的handler,可能会同时把log写入到不同的log文件中。
        logger.addHandler(handler) # 设置新的handler
        return logger

 

性能分析

if __name__ == '__main__':
    i = 0
    t = time.time()
    while i < 10000:
        logger = LogSingleton.get_logger_v2()
        i += 1
    print('v2: %.3fs' % (time.time() - t))

    i = 0
    t = time.time()
    while i < 10000:
        logger = LogSingleton.get_logger_v1()
        i += 1
    print('v1: %.3fs' % (time.time() - t))

耗时如下:

v2: 0.106s
v1: 1.394s

Process finished with exit code 0

一万次耗时,可以相差近14倍,这次优化效果还是很可观的。

End

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值