Python日志—Python日志模块logging介绍

Python012

Python日志—Python日志模块logging介绍,第1张

从事与软件相关工作的人,应该都听过“日志”一词。

日志就是跟踪软件运行时事件的方法,为了能够在程序运行过程中记录错误。

通过日志记录程序的运行,方便我们查询信息,以便追踪问题、进行维护和调试、还是数据分析。

并且各编程语言都形成了各自的日志体系和相应的框架。

日志的作用总结:

首先我们要树立一个观点,那就是“不是为了记录日志而记录日志,日志也不是随意记的”。要实现能够只通过日志文件还原整个程序执行的过程,达到能透明地看到程序里执行情况,每个线程每个过程到底执行结果的目的。日志就像飞机的黑匣子一样,应当能够复原异常的整个现场乃至细节。

在项目中,日志这个功能非常重要,我们要重视起来。

在Python中,使用logging模块来进行日志的处理。

logging是Python的内置模块,主要用于将日志信息进行格式化内容输出,可将格式化内容输出到文件,也可输出到屏幕。

我们在开发过程中,常用print()函数来进行调试,但是在实际应用的部署时,我们要将日志信息输出到文件中,方便后续查找以及备份。

在我们使用日志管理时,我们也可以将日志格式化成Json对象转存到ELK中方便图形化查看及管理。

logging模块将日志系统从高向低依次定义了四个类,分别是logger(日志器)、handler(处理器)、filter(过滤器)和formatter(格式器)。其中由日志器生成的实例将接管原本日志记录函数logging.log的功能。

说明:

我们先来思考下下面的两个问题:

在软件开发阶段或部署开发环境时,为了尽可能详细的查看应用程序的运行状态来保证上线后的稳定性,我们可能需要把该应用程序所有的运行日志全部记录下来进行分析,这是非常耗费机器性能的。

当应用程序正式发布或在生产环境部署应用程序时,我们通常只需要记录应用程序的异常信息、错误信息等,这样既可以减小服务器的I/O压力,也可以避免我们在排查故障时被淹没在日志的海洋里。

那么怎样才能在不改动应用程序代码的情况下,根据事件的重要性或者称之为等级,实现在不同的环境中,记录不同详细程度的日志呢?

这就是日志等级的作用了,我们通过配置文件指定我们需要的日志等级就可以了。

说明:

总结:

开发应用程序时或部署开发环境时,可以使用DEBUG或INFO级别的日志获取尽可能详细的日志信息,可以方便进行开发或部署调试。 应用上线或部署生产环境时,应用使用WARNING或ERROR或CRITICAL级别的日志,来降低机器的I/O压力和提高获取错误日志信息的效率。 日志级别的指定通常都是在应用程序的配置文件中进行指定的。 不同的应用程序所定义的日志等级会有所差别,根据实际需求来决定。

日志的记录

Python有一个logging模块,可以用来产生日志。

(1)学习资料

http://blog.sina.com.cn/s/blog_4b5039210100f1wv.html

http://blog.donews.com/limodou/archive/2005/02/16/278699.aspx

http://kenby.iteye.com/blog/1162698

http://blog.csdn.NET/fxjtoday/article/details/6307285

前边几篇文章仅仅是其它人的简单学习经验,下边这个链接中的内容比较全面。

http://www.red-dove.com/logging/index.html

(2)我需要关注内容

日志信息输出级别

logging模块提供了多种日志级别,如:NOTSET(0),DEBUG(10),

INFO(20),WARNING(30),WARNING(40),CRITICAL(50)。

设置方法:

logger = getLogger()

logger.serLevel(logging.DEBUG)

日志数据格式

使用Formatter设置日志的输出格式。

设置方法:

logger = getLogger()

handler = loggingFileHandler(XXX)

formatter = logging.Formatter("%(asctime)s %(levelname) %(message)s","%Y-%m-%d,%H:%M:%S")

%(asctime)s表示记录日志写入时间,"%Y-%m-%d,%H:%M:%S“设定了时间的具体写入格式。

%(levelname)s表示记录日志的级别。

%(message)s表示记录日志的具体内容。

日志对象初始化

def initLog():

logger = logging.getLogger()

handler = logging.FileHandler("日志保存路径")

formatter = logging.Formatter("%(asctime)s %(levelname) %(message)s","%Y-%m-%d,%H:%M:%S")

handler.setFormatter(formatter)

logger.addHandler(handler)

logger.setLevel

写日志

logging.getLogger().info(), logging.getLogger().debug()......

2. 日志的分析。

(1)我的日志的内容。(log.txt)

2011-12-12,12:11:31 INFO Client1: 4356175.0 1.32366309133e+12 1.32366309134e+12

2011-12-12,12:11:33 INFO Client1: 4361320.0 1.32366309334e+12 1.32366309336e+12

2011-12-12,12:11:33 INFO Client0: 4361320.0 1.32366309389e+12 1.32366309391e+12

2011-12-12,12:11:39 INFO Client1: 4366364.0 1.32366309934e+12 1.32366309936e+12

2011-12-12,12:11:39 INFO Client0: 4366364.0 1.32366309989e+12 1.32366309991e+12

2011-12-12,12:11:43 INFO Client1: 4371416.0 1.32366310334e+12 1.32366310336e+12

2011-12-12,12:11:43 INFO Client0: 4371416.0 1.32366310389e+12 1.32366310391e+12

2011-12-12,12:11:49 INFO Client1: 4376450.0 1.32366310934e+12 1.32366310936e+12

我需要将上述内容逐行读出,并将三个时间戳提取出来,然后将其图形化。

(2) 文件操作以及字符串的分析。

打开文件,读取出一行日志。

file = file("日志路径",“r”)

while True:

line = file.readline()

if len(len) == 0:

break

print line

file.close()

从字符串中提取数据。

字符串操作学习资料:

http://reader.youdao.com/sharelite?itemId=-4646262544179865983&method=viewSharedItemThroughLink&sharedBy=-1137845767117085734

从上面展示出来的日志内容可见,主要数据都是用空格分隔,所以需要使用字符串的

split函数对字符串进行分割:

paraList = line.split(),该函数默认的分割符是空格,返回值为一个list。

paraList[3], paraList[4], paraList[5]中分别以字符串形式存储着我需要的时间戳。

使用float(paraList[3])将字符串转化为浮点数。

(3)将日志图形化。

matplotlib是python的一个绘图库。我打算用它来将日志图形化。

matplotlib学习资料。

matplotlib的下载与安装:

http://yexin218.iteye.com/blog/645894

http://blog.csdn.Net/sharkw/article/details/1924949

对matplotlib的宏观介绍:

http://apps.hi.baidu.com/share/detail/21928578

对matplotlib具体使用的详细介绍:

http://blog.sina.com.cn/s/blog_4b5039210100ie6a.html

在matplotlib中设置线条的颜色和形状:

http://blog.csdn.net/kkxgx/article/details/python

如果想对matplotlib有一个全面的了解,就需要阅读教程《Matplotlib for Python developers》,教程下载地址:

http://download.csdn.net/detail/nmgfrank/4006691

使用实例

import matplotlib.pyplot as plt

listX = [] #保存X轴数据

listY = [] #保存Y轴数据

listY1 = [] #保存Y轴数据

file = file("../log.txt","r")#打开日志文件

while True:

line = file.readline()#读取一行日志

if len(line) == 0:#如果到达日志末尾,退出

break

paraList = line.split()

print paraList[2]

print paraList[3]

print paraList[4]

print paraList[5]

if paraList[2] == "Client0:": #在坐标图中添加两个点,它们的X轴数值是相同的

listX.append(float(paraList[3]))

listY.append(float(paraList[5]) - float(paraList[3]))

listY1.append(float(paraList[4]) - float(paraList[3]))

file.close()

plt.plot(listX,listY,'bo-',listX,listY1,'ro')#画图

plt.title('tile')#设置所绘图像的标题

plt.xlabel('time in sec')#设置x轴名称

plt.ylabel('delays in ms'')#设置y轴名称

plt.show()

#coding:utf-8

#file: FileSplit.py

import os,os.path,time

def FileSplit(sourceFile, targetFolder):

sFile = open(sourceFile, 'r')

number = 100000 #每个小文件中保存100000条数据

dataLine = sFile.readline()

tempData = [] #缓存列表

fileNum = 1

if not os.path.isdir(targetFolder): #如果目标目录不存在,则创建

os.mkdir(targetFolder)

while dataLine: #有数据

for row in range(number):

tempData.append(dataLine) #将一行数据添加到列表中

dataLine = sFile.readline()

if not dataLine :

break

tFilename = os.path.join(targetFolder,os.path.split(sourceFile)[1] + str(fileNum) + ".txt")

tFile = open(tFilename, 'a+') #创建小文件

tFile.writelines(tempData) #将列表保存到文件中

tFile.close()

tempData = [] #清空缓存列表

print(tFilename + " 创建于: " + str(time.ctime()))

fileNum += 1 #文件编号

sFile.close()

if __name__ == "__main__" :

FileSplit("access.log","access")

#coding:utf-8

#file: Map.py

import os,os.path,re

def Map(sourceFile, targetFolder):

sFile = open(sourceFile, 'r')

dataLine = sFile.readline()

tempData = {} #缓存列表

if not os.path.isdir(targetFolder): #如果目标目录不存在,则创建

os.mkdir(targetFolder)

while dataLine: #有数据

p_re = re.compile(r'(GET|POST)\s(.*?)\sHTTP/1.[01]',re.IGNORECASE) #用正则表达式解析数据

match = p_re.findall(dataLine)

if match:

visitUrl = match[0][1]

if visitUrl in tempData:

tempData[visitUrl] += 1

else:

tempData[visitUrl] = 1

dataLine = sFile.readline() #读入下一行数据

sFile.close()

tList = []

for key,value in sorted(tempData.items(),key = lambda k:k[1],reverse = True):

tList.append(key + " " + str(value) + '\n')

tFilename = os.path.join(targetFolder,os.path.split(sourceFile)[1] + "_map.txt")

tFile = open(tFilename, 'a+') #创建小文件

tFile.writelines(tList) #将列表保存到文件中

tFile.close()

if __name__ == "__main__" :

Map("access\\access.log1.txt","access")

Map("access\\access.log2.txt","access")

Map("access\\access.log3.txt","access")

#coding:utf-8

#file: Reduce.py

import os,os.path,re

def Reduce(sourceFolder, targetFile):

tempData = {} #缓存列表

p_re = re.compile(r'(.*?)(\d{1,}$)',re.IGNORECASE) #用正则表达式解析数据

for root,dirs,files in os.walk(sourceFolder):

for fil in files:

if fil.endswith('_map.txt'): #是reduce文件

sFile = open(os.path.abspath(os.path.join(root,fil)), 'r')

dataLine = sFile.readline()

while dataLine: #有数据

subdata = p_re.findall(dataLine) #用空格分割数据

#print(subdata[0][0]," ",subdata[0][1])

if subdata[0][0] in tempData:

tempData[subdata[0][0]] += int(subdata[0][1])

else:

tempData[subdata[0][0]] = int(subdata[0][1])

dataLine = sFile.readline() #读入下一行数据

sFile.close()

tList = []

for key,value in sorted(tempData.items(),key = lambda k:k[1],reverse = True):

tList.append(key + " " + str(value) + '\n')

tFilename = os.path.join(sourceFolder,targetFile + "_reduce.txt")

tFile = open(tFilename, 'a+') #创建小文件

tFile.writelines(tList) #将列表保存到文件中

tFile.close()

if __name__ == "__main__" :

Reduce("access","access")