在一个项目中,日志模块是必不可少的,健壮的日志输出有助于及时发现问题和调试。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会直接发送致命错误邮件提醒。
使用了这个日志配置之后,我们就可以高枕无忧的干其他事情了,只要没有邮件提醒,程序都在正常运行。。
一旦收到邮件后,及时查看文件日志,也不难找出错误。
分享到:
相关推荐
目前我做的一个爬虫项目,程序由计划任务定时执行,程序一旦跑起来就不会天天去关注,所以对日志模块就以下四个要求。 1.详细的debug信息写入文件,一旦程序出错,可以在文件里面找到详细的出错信息 2.控制台实时...
Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用。这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET/POST,SMTP,Socket等,甚至可以自己实现具体的日志...
主要介绍了Python logging模块用法,结合实例形式分析了Python logging模块相关配置、函数、组件等操作方法与注意事项,需要的朋友可以参考下
主要介绍了Python使用logging模块实现打印log到指定文件的方法,结合实例形式分析了Python logging模块的原理及相关日志输出操作技巧,需要的朋友可以参考下
首先介绍下怎么发现的吧, 线上的项目日志是通过 logging 模块打到 syslog 里, 跑了一段时间后发现 syslog 的 UDP 连接超过了 8W, 没错是 8 W. 主要是 logging 模块用的不对 我们之前有这么一个需求, 就是针对每一个...
主要介绍了python 日志 logging模块 详细解析,本文通过实例代码给大家介绍的非常详细,对大家的工作或学习具有一定的参考借鉴价值,需要的朋友可以参考下
logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;相比print,具备如下优点: 可以通过设置不同的日志等级,在release版本中只输出重要信息,而...
本文实例讲述了Python日志logging模块功能与用法。分享给大家供大家参考,具体如下: 本文内容: logging模块的介绍 logging模块的基础使用 logging模块的扩展使用 logging中的Filter 使用配置文件配置logging...
本文实例讲述了python日志logging模块使用方法。分享给大家供大家参考,具体如下: 一、从一个使用场景开始 开发一个日志系统, 既要把日志输出到控制台, 还要写入日志文件 import logging # 创建一个logger ...
主要介绍了Python内置模块logging用法,结合实例形式较为详细的分析了Python基于logging模块的日志配置、输出等常用操作技巧,需要的朋友可以参考下
本文实例讲述了logging模块的用法实例,分享给大家供大家参考。具体方法如下:import loggingimport os log = logging.getLogger()formatter = logging.Formatter('[%(asctime)s] [%(name)s] %(levelname)s: %...
主要介绍了Python中使用logging模块打印log日志详解,本文讲解了logging模块介绍、基本使用方法、高级使用方法、使用实例等,需要的朋友可以参考下
利用以上python代码配置日志输出时,如果该脚本是主脚本(即import别人,不被别人import,在执行逻辑的最顶端),path表示的日志配置文件只能与该脚本在同一目录下或者在其子文件夹里。 import sys sys.path.append...
本文实例讲述了Python 日志logging模块用法。分享给大家供大家参考,具体如下: demo.py(日志,输出到控制台): import logging # 导入logging模块 # 日志级别默认是WARNING logging.basicConfig(level=logging....
主要介绍了Python3.6日志Logging模块简单用法,结合实例形式分析了Python3.6环境下日志Logging模块设置格式、文件流输出相关操作技巧,需要的朋友可以参考下
最近写一个爬虫系统,需要用到python的日志记录模块,于是便学习了一下。python的标准库里的日志系统从Python2.3开始支持。只要import logging这个模块即可使用。如果你想开发一个日志系统, 既要把日志输出到控制台...