`
zoulc001
  • 浏览: 30472 次
  • 性别: Icon_minigender_1
  • 来自: 成都
文章分类
社区版块
存档分类
最新评论

在项目中定制python的logging模块的实例

 
阅读更多

在一个项目中,日志模块是必不可少的,健壮的日志输出有助于及时发现问题和调试。python的日志模块logging为我们提供了强大的日志功能。

一.logging模块简介

我们先看一个标准的程序:

import logging
logger=logging.getLogger()
handler=logging.FileHandler("Log_test.txt")
logger.addHandler(handler)
logger.setLevel(logging.NOTSET)
logger.error("This is an error message")
logger.info("This is an info message")
logger.critical("This is a critical message")
 

这个程序应用了logging中常用的filehandler,在日志文件中会出现三行内容:

This is an error message

This is an info message

This is a critical message

上面程序的第2行是生成一个日志对象,里面的参数时日志的名字,可以带,也可以不带。第3行是生成了一个handler,logging支持很多种 Handler,像FileHandler,SocketHandler等待,这里由于我们要写文件,所以用了FileHandler,它的参数就是 filename,默认当前路径,当然我们可以自己指定路径。

第5行设置日志信息输出的级别。Logging提供了多种日志级别,如 NOTSET,DEBUG,INFO,WARNING,ERROR,CRITICAL等,每个级别都对应一个数值,如果我们不自己设置输出级别,那么系统 会执行缺省级别,值为30,就warning。当写入日志时,小于指定级别的信息将被忽略。因此为了输出想要的日志级别一定要设置好此参数。这里我设为NOTSET(值为0),也就是想输出所有信息。

 

关于logging模块的详细介绍,以及程序实例,可以参考这个链接

http://www.red-dove.com/python_logging.html

 

二.实际项目中的应用

目前我做的一个爬虫项目,程序由计划任务定时执行,程序一旦跑起来就不会天天去关注,所以对日志模块就以下四个要求。

1.详细的debug信息写入文件,一旦程序出错,可以在文件里面找到详细的出错信息

2.控制台实时打印重要信息,如一些error和warning

3.由于程序属于无人监管状态,当一般错误信息达到一定数量后,自动发邮件提醒。

4.出现重大的错误后,单独发邮件提醒,并挂起程序。如数据库死掉,磁盘阵列无法访问等。

 

综合以上的要求,我需要用到logging中得FileHandler(由于日志量会很大,这里需要用到RotatingFileHandler,日志达到设定大小后自动写到另外的文件中),Streamhandler(往控制台输出日志),SMTPHanler(用于致命错误的邮件提醒), MemoryHandler(用于缓存一般错误日志,达到阀值之后自动邮件提醒).

logging的配置如下:

#encoding=utf-8
import logging
import time
import smtplib
from email.mime.text import MIMEText
import logging.handlers
import os
#日志文件的路径,FileHandler不能创建目录,这里先检查目录是否存在,不存在创建他
#当然也可以继承之后重写FileHandler的构造函数
LOG_FILE_PATH="log/Execution.log"
dir= os.path.dirname(LOG_FILE_PATH)
if not os.path.isdir(dir):
    os.mkdir(dir)
#写入文件的日志等级,由于是详细信息,推荐设为debug
FILE_LOG_LEVEL="DEBUG"
#控制台的日照等级,info和warning都可以,可以按实际要求定制
CONSOLE_LOG_LEVEL="INFO"
#缓存日志等级,最好设为error或者critical
MEMOEY_LOG_LEVEL="ERROR"
#致命错误等级 
URGENT_LOG_LEVEL="CRITICAL"
#缓存溢出后的邮件标题
ERROR_THRESHOLD_ACHEIVED_MAIL_SUBJECT="Too many errors occurred during the execution"
#缓存溢出的阀值
ERROR_MESSAGE_THRESHOLD=50
#致命错误发生后的邮件标题
CRITICAL_ERROR_ACHEIVED_MAIL_SUBJECT="Fatal error occurred"

#邮件服务器配置
MAIL_HOST="your exchange server"
FROM="from"
MAIL_TO=["address1","address2"]

class OptmizedMemoryHandler(logging.handlers.MemoryHandler):
    """
       由于自带的MemoryHandler达到阀值后,每一条缓存信息会单独处理一次,这样如果阀值设的100,
      会发出100封邮件,这不是我们希望看到的,所以这里重写了memoryHandler的2个方法,
      当达到阀值后,把缓存的错误信息通过一封邮件发出去.
    """
    def __init__(self, capacity,mail_subject):
        logging.handlers.MemoryHandler.__init__(self, capacity,flushLevel=logging.ERROR, target=None)
        self.mail_subject=mail_subject
        self.flushed_buffers=[]
    def shouldFlush(self, record):
        """
        检查是否溢出
        """
        if len(self.buffer) >= self.capacity:
            return True
        else:
            return False
    def flush(self):
        """
         缓存溢出时的操作,
        1.发送邮件 2.清空缓存 3.把溢出的缓存存到另一个列表中,方便程序结束的时候读取所有错误并生成报告
        """
        if self.buffer!=[] and len(self.buffer) >= self.capacity:
            content=""
            for record in self.buffer:
                message= record.getMessage()
                level= record.levelname
                ctime= record.created
                t=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(ctime))
                content+=t+" "+"*"+level+"* : "+message+"\n"
            self.mailNotification(self.mail_subject, content)
            self.flushed_buffers.extend(self.buffer)
            self.buffer = []
    def mailNotification(self,subject,content):
        """
                发邮件的方法
        """
        msg=MIMEText(content)
        msg['Subject']=subject
        msg['From']=FROM
        msg['To']=";".join(MAIL_TO)
        try:
            s=smtplib.SMTP()
            s.connect(MAIL_HOST)
            s.sendmail(FROM,MAIL_TO,msg.as_string())
            s.close()
        except Exception,e:
            self.logger.error(str(e))

            
MAPPING={"CRITICAL" :50,
           "ERROR" : 40,
           "WARNING" : 30,
           "INFO" : 20,
           "DEBUG" : 10,
           "NOTSET" :0,
           }

class logger:
    """
    logger的配置
    """
    def __init__(self,logFile,file_level,console_level,memory_level,urgent_level):

        self.config(logFile, file_level, console_level, memory_level,urgent_level)
    def config(self,logFile,file_level,console_level,memory_level,urgent_level):
        #生成root logger
        self.logger = logging.getLogger("crawler")
        self.logger.setLevel(MAPPING[file_level])
        #生成RotatingFileHandler,设置文件大小为10M,编码为utf-8,最大文件个数为100个,如果日志文件超过100,则会覆盖最早的日志
        self.fh = logging.handlers.RotatingFileHandler(logFile,mode='a', maxBytes=1024*1024*10, backupCount=100, encoding="utf-8")
        self.fh.setLevel(MAPPING[file_level])
        #生成StreamHandler
        self.ch = logging.StreamHandler()
        self.ch.setLevel(MAPPING[console_level])  
        #生成优化过的MemoryHandler,ERROR_MESSAGE_THRESHOLD是错误日志条数的阀值
        self.mh = OptmizedMemoryHandler(ERROR_MESSAGE_THRESHOLD,ERROR_THRESHOLD_ACHEIVED_MAIL_SUBJECT)
        self.mh.setLevel(MAPPING[memory_level])
        #生成SMTPHandler
        self.sh=logging.handlers.SMTPHandler(MAIL_HOST,FROM,";".join(MAIL_TO),CRITICAL_ERROR_ACHEIVED_MAIL_SUBJECT)
        self.sh.setLevel(MAPPING[urgent_level])
        #设置格式
        formatter = logging.Formatter("%(asctime)s *%(levelname)s* : %(message)s",'%Y-%m-%d %H:%M:%S')  
        self.ch.setFormatter(formatter)  
        self.fh.setFormatter(formatter)
        self.mh.setFormatter(formatter)
        self.sh.setFormatter(formatter)
        #把所有的handler添加到root logger中
        self.logger.addHandler(self.ch)  
        self.logger.addHandler(self.fh)
        self.logger.addHandler(self.mh)
        self.logger.addHandler(self.sh)

    def debug(self,msg):
        if msg is not None:
            self.logger.debug(msg)
    def info(self,msg):
        if msg is not None:
            self.logger.info(msg)
    def warning(self,msg):
        if msg is not None:
            self.logger.warning(msg)
    def error(self,msg):
        if msg is not None:
            self.logger.error(msg)
    def critical(self,msg):
        if msg is not None:
            self.logger.critical(msg)
LOG=logger(LOG_FILE_PATH,FILE_LOG_LEVEL,CONSOLE_LOG_LEVEL,MEMOEY_LOG_LEVEL,URGENT_LOG_LEVEL)
if __name__=="__main__":
    #测试代码
    for i in range(50):
        LOG.error(i)
        LOG.debug(i)
    LOG.critical("Database has gone away")

在主程序中,只需要把LOG对象import进去,就可以通过LOG提供的info,debug。。。的方法输入日志。

当输入一条debug日志,由于等级是最低的,只有RotatingFileHandler的日志等级与之匹配,所以文件中会记录这条debug信息。

当输入一条error日志时,匹配日志等级,文件中会记录这条日志,控制台中会打印出来,MemoryHandler模块会缓存这条日志,并判断是否达到溢出条件。

当输入一条critical日志时,匹配日志等级,文件中会记录这条日志,控制台中会打印出来,MemoryHandler模块会缓存这条日志,并判断是否达到溢出条件,同时SMTPHandler会直接发送致命错误邮件提醒。

 

使用了这个日志配置之后,我们就可以高枕无忧的干其他事情了,只要没有邮件提醒,程序都在正常运行。。

一旦收到邮件后,及时查看文件日志,也不难找出错误。

分享到:
评论

相关推荐

    python的logging模块

    ### Python的logging模块详解 #### 一、简介与应用场景 在进行Python开发时,日志模块是必不可少的一部分,尤其对于大型或复杂的项目来说更是如此。Python内置的`logging`模块提供了一种简单且灵活的方式来记录...

    python logging实例

    目前我做的一个爬虫项目,程序由计划任务定时执行,程序一旦跑起来就不会天天去关注,所以对日志模块就以下四个要求。 1.详细的debug信息写入文件,一旦程序出错,可以在文件里面找到详细的出错信息 2.控制台实时...

    Python logging模块handlers用法详解

    Python的logging模块是用于处理程序运行过程中的日志记录,它提供了一种灵活且强大的方式来跟踪应用程序的行为。本文将深入探讨logging模块中的handlers,这是日志处理的核心组件,它们负责将日志信息发送到不同的...

    Python logging模块写入中文出现乱码

    - 封装日志模块,创建自定义的日志类,便于在项目中统一管理和使用日志。 通过以上分析,我们可以看出,解决`logging`模块写入中文出现乱码的问题关键在于正确设置文件处理器的编码。同时,了解`logging`模块的基本...

    解决Python logging模块无法正常输出日志的问题

    在Python编程中,logging模块是用于生成日志的标准库,它提供了灵活的日志记录功能,包括不同级别的日志(如DEBUG、INFO、WARNING、ERROR、CRITICAL)以及日志输出到控制台、文件或其他处理器的能力。然而,有时我们...

    Python使用logging模块实现打印log到指定文件的方法

    在Python中,logging模块是一个强大的日志记录工具,它允许用户将程序运行期间产生的日志信息输出到控制台或者写入到文件中。在大型项目中,将日志信息记录到文件中是非常重要的,因为它可以帮助开发人员或者运维...

    Python logging模块进行封装实现原理解析

    ### Python logging模块封装实现原理详解 #### 一、引言 在软件开发过程中,日志记录是一项非常重要的功能。它不仅能够帮助开发者更好地理解和调试代码,还能为运维人员提供系统运行状态的重要信息。Python自带的...

    Python库 | python-logging-loki-0.2.0.tar.gz

    在IT行业中,Python是一种广泛应用的高级编程语言,以其简洁易读的语法和强大的库支持而闻名。本资源“python-logging-loki-0.2.0.tar.gz”是针对Python开发的一个特定库,名为“logging-loki”,版本为0.2.0。这个...

    python logging模块书写日志以及日志分割详解

    5. **添加处理器到 Logger**:最后将这两个处理器添加到 Logger 实例中。 6. **记录日志**:使用 `logger.info()`, `logger.error()` 和 `logger.critical()` 方法记录不同级别的日志信息。 #### 六、总结 通过...

    Python中内置的日志模块logging用法详解

    Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用。这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET/POST,SMTP,Socket等,甚至可以自己实现具体的日志...

    解决Python中由于logging模块误用导致的内存泄露

    首先介绍下怎么发现的吧, 线上的项目日志是通过 logging 模块打到 syslog 里, 跑了一段时间后发现 syslog 的 UDP 连接超过了 8W, 没错是 8 W. 主要是 logging 模块用的不对 我们之前有这么一个需求, 就是针对每一个...

    python 日志 logging模块详细解析

    Python 的 `logging` 模块是用于记录程序运行过程中各种事件的重要工具,它提供了一种标准的方法来输出不同级别的日志信息,包括调试(debug)、信息(informational)、警告(warnings)、错误(error)和严重错误...

    python日志输出----logging浅析与使用

    ### Python日志输出详解——深入理解logging模块 在Python编程中,日志系统扮演着至关重要的角色,尤其是在处理复杂项目时。它不仅帮助开发者追踪软件运行过程中的各种事件,还能在遇到问题时提供宝贵的线索。...

    详解使用python的logging模块在stdout输出的两种方法

    ### 使用Python的Logging模块在Stdout输出的两种方法 #### 前言 在Python开发过程中,使用`logging`模块来记录程序运行时的日志是非常常见的做法。这不仅可以帮助我们更好地跟踪程序的状态,还能在出现问题时提供...

    Python logging模块用法示例

    本文将详细介绍Python logging模块的基本用法,并结合实例进行讲解,包括相关配置、函数、组件等操作方法以及注意事项。 首先,介绍logging模块的一些基本概念。logging模块中最重要的几个组件是Logger(记录器)、...

    Python中logger日志模块详解

    logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;相比print,具备如下优点: 可以通过设置不同的日志等级,在release版本中只输出重要信息,而...

    python logging日志模块以及多进程日志详解

    在Python logging模块中,每个logger都有一个日志级别。这个级别决定了该logger需要处理的日志级别。logging模块中定义了以下级别: - DEBUG:最低的日志级别,用于记录诊断信息。 - INFO:表明信息性质的日志。 - ...

    Python logging模块异步线程写日志实现过程解析

    在Python中,`logging`模块是用于日志记录的标准库,它提供了多种级别的日志记录(如DEBUG、INFO、WARNING、ERROR等)以及灵活的日志配置。然而,在高并发或性能敏感的应用中,同步写入日志可能会成为程序性能的瓶颈...

    python爬取小说实例(仅供参考)

    4. **多线程**:为了提高爬取效率,实例中可能使用了Python的`threading`模块,创建多个线程同时进行爬取。这样可以并发处理多个请求,但需要注意线程同步和资源管理以避免冲突。 5. **代理IP池**:为了避免被目标...

    python logging模块的使用

    Python的logging模块是用于生成日志的标准库,它提供了丰富的功能,可以帮助开发者记录程序运行过程中的各种信息,从错误和警告到调试信息。这个模块的使用对于任何Python项目都是至关重要的,因为它能帮助追踪和...

Global site tag (gtag.js) - Google Analytics