在程序开发过程中,通常会需要错误排查的语句,除了使用输出print或者echo之类的语句外,在python中logging日志模块也可以派上用场。logging模块可以用于记录程序执行的过程,这样非常有利于监测程序运行状态,不光可以在控制台看到运行过程,还可以将日志记录输出到文件里。下面将logging库常用方法及实践案例介绍如下。
(1)logging日志导入
logging是python自带的标准库,无需使用pip来安装。使用时如datetime、random等模块一样直接使用import logging方式即可。
import logging
(2)logging初次使用
使用的时候,先设置一下logging的basicConfig基本配置参数:
logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(levelname)s - %(lineno)d - %(message)s ')
然后定义一个logger对象,调用logging模块的getLogger方法。
logger = logging.getLogger()
然后就可以在程序代码中使用了:
import logging
logging.basicConfig(level=logging.INFO,format='%(asctime)s-%(levelname)s-%(lineno)d-%(message)s')
logger = logging.getLogger()
logger.info("程序开始执行...")
def cal_area(radius=None):
return 3.14*radius*radius
radius = eval(input("请输入半径的值:"))
if radius <=0:
logger.warning("半径不能小于0...")
logger.info("开始计算面积...")
area = cal_area(radius=radius)
logger.info("计算面积结果为:{area}".format(area=area))
运行后,终端显示出来结果为:
F:\learn-Python\tt\venv\Scripts\python.exe F:/learn-Python/tt/test/circle.py
2020-02-19 11:41:57,348 - INFO - 8 - 程序开始执行...
请输入半径的值: 15
2020-02-19 11:42:09,277 - INFO - 17 - 开始计算面积...
2020-02-19 11:42:09,277 - INFO - 19 - 计算面积结果为:706.5
Process finished with exit code 0
如上显示,我们将程序执行过程在终端就记录下来了。
如果想将这个记录存成文件输出,简单操作就是只需要增加一下filename指定就可以:
logging.basicConfig(level=logging.INFO,filename='1.log')
就是在basicConfig参数里将filename参数指定下来,如上面程序代码我们修改一下:
import logging
logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(levelname)s - %(lineno)d - %(message)s ',filename='1.log')
logger = logging.getLogger()
logger.info("程序开始执行...")
def cal_area(radius=None):
return 3.14*radius*radius
radius = eval(input("请输入半径的值:"))
if radius <=0:
logger.warning("半径不能小于0...")
logger.info("开始计算面积...")
area = cal_area(radius=radius)
logger.info("计算面积结果为:{area}".format(area=area))
执行程序时,有关日志就不再会在终端打印了,而是都写到了指定的1.log文件中。
(3)logging应用详解
上面我们通过程序的实践都实现了日志的终端输出和文件记录。这样实现后,以后再在代码中我们就可以不去使用print方式输出有些可能存在代码错误的地方,非常方便监测程序运行状态。下面就一些可以调整的参数做个实践和介绍。basicConfig里的level级别: 这是设置打印日志级别,低于该级别的就不打印输出,高于的才记录。所以有必要了解这个level级别设置。在logging模块里,一共分了5个级别:
1.DEBUG:详细信息,用于诊断问题。Value=10。
2.INFO:确认代码运行正常。Value=20。
3.WARNING:意想不到的事情发生了,或预示着某个问题。但软件仍按预期运行。value=30
4.ERROR:出现更严重的问题,软件无法执行某些功能。Value=40。
5.CRITICAL:严重错误,程序本身可能无法继续运行。Value=50
这5个级别从重要性来看,肯定4和5要严重一些。但从全面性来看,1和2记录信息更详细一些。所以在basicConfig(level=logging.LEVEL)这个LEVEL参数这可以用上述5个英文单词替换。使用LEVEL为DEBUG或者INFO时,就是较为详细的记录日志。
2. basicConfig里的format,这是日志输出时的格式定义。上述代码中format=‘%(asctime)s’这个asctime参数是当前时间,%s 是以字符串格式输出。'%(levelname)s' 这个levelname就是级别名称,包括INFO、WARNING、ERROR和CRITICAL等。’%(lineno)d‘这个是日志输出所在的行号,以%d整型方式输出。’%(message)s‘这里的message就是消息参数,后面在http://logger.info(message)这里给出具体的值。而logging模块里还有很多类似的格式控制符:
%(levelno)s: 打印日志级别的数值
%(levelname)s: 打印日志级别名称
%(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s: 打印当前执行程序名
%(funcName)s: 打印日志的当前函数
%(lineno)d: 打印日志的当前行号
%(asctime)s: 打印日志的时间
%(thread)d: 打印线程ID
%(threadName)s: 打印线程名称
%(process)d: 打印进程ID
%(message)s: 打印日志信息
我们可以测试一下,打印一下filename信息:
import logging
logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s ',filename='2.log')
logger = logging.getLogger()
logger.info("程序开始执行...")
def cal_area(radius=None):
return 3.14*radius*radius
radius = eval(input("请输入半径的值:"))
if radius <=0:
logger.warning("半径不能小于0...")
logger.info("开始计算面积...")
area = cal_area(radius=radius)
logger.info("计算面积结果为:{area}".format(area=area))
输出的日志文件中内容为:
2020-02-19 13:09:18,021 - circle.py[line:5] - INFO: 程序开始执行...
2020-02-19 13:09:20,885 - circle.py[line:14] - INFO: 开始计算面积...
2020-02-19 13:09:20,885 - circle.py[line:16] - INFO: 计算面积结果为:78.5
3. 如果将basicConfig配置拆分,变为直接对象属性设置,如果想直接在控制台输出,可以设置输出流StreamHandler:
import logging
log_level =logging.INFO
logger = logging.getLogger("for this file")
logger.setLevel(log_level)
#控制台输出流,设置输出级别
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
#创建formatter格式化器
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
#将formatter 添加到ch处理器
ch.setFormatter(formatter)
#将ch添加到logger
logger.addHandler(ch)
logger.info("the program starting ... ")
def test():
print("welcome to my apps!")
test()
logger.info('程序执行完成...')
如果想输出为日志文件,则可以这样:
import logging
log_file = '4.log'
log_level =logging.INFO
logger = logging.getLogger("for this file")
logger.setLevel(log_level)
#文件流输出,设置输出级别
fh = logging.FileHandler(log_file)
fh.setLevel(logging.DEBUG)
#创建formatter格式化器
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
#将formatter 添加到ch处理器
fh.setFormatter(formatter)
#将ch添加到logger
logger.addHandler(fh)
logger.info("the program starting ... ")
def test():
print("welcome to my apps!")
test()
logger.info('程序执行完成...')
输出在4.log文件里,打开为:
2020-02-19 13:32:21,407 - for this file - INFO - the program starting ...
2020-02-19 13:32:21,407 - for this file - INFO - 程序执行完成...
(4)logging模块应用实践
从上面我们实践的简单例子来看,都是将logging日志配置相关代码与实际程序运行代码混杂在一起的,这样显得程序比较重,当然我们都还是用的简单程序,如果是复杂的工程类项目,每个业务代码里都嵌入这样的logging配置肯定是不科学的,因此一般在实际应用中通常会单独来个python包或者模块用于配置logging,然后其他的业务代码文件中直接import来使用。
我们来实践一下,首先我们建立一个py文件,命名为logBase.py,专门用于设置logging相关配置:
import logging
class logBase(): #建立日志类
def __init__(self,appName=None):
self.log_level = logging.INFO #设置日志级别
self.appName = appName #设置当前程序名
def logCreator(self): #创建日志
logging.basicConfig(level=self.log_level,format='%(asctime)s - %(name)s - %(lineno)d - %(message)s')
logger = logging.getLogger(self.appName)
return logger
然后我们可以在同一级别目录下新建另外一个py文件,命名为main.py,输入如下代码:
from .logBase import logBase #导入日志配置文件
logger = logBase(appName='main').logCreator() #建立一个日志对象
class Weather():
def __init__(self):
pass
def RecordInfo(self):
print("接最新天气预报.....")
print("今天,天津天气,雨雾,湿气大,不适宜出门")
def Action(self,choice=None):
if not choice:
logger.warning("还没给出选择方案...")
return False
elif choice == '1':
msg = "我们在家做好吃的东西,然后开个PARTY"
elif choice == '2':
msg = '我们还是想出去转转,试试看是否有新的发现'
logger.info("执行方案: {choice}".format(choice=choice))
return msg
if __name__=='__main__':
logger.info('start to connect with weather database ...') #加入日志记录
t = Weather()
t.RecordInfo()
print(t.Action())
也就是当创建好日志logging配置文件后,在其他模块或者业务代码中只需要导入这个模块,然后开始使用logger对象就可以进行日志记录了。这样就方便了很多。
更多推荐
python中的logging记录日志_python上手 -- 使用logging日志模块
发布评论