程序异常的时候最好找到异常出处的方法是查看日志。给程序打上日志的目的是减少后期的工作量,所以给程序打上日志是一位优秀coder必备的基本技能之一。
在Python中用到的日志记录库,通常是Python内置的logging标准库。虽然logging标准库采用的是模块化设计,可以设置不同的handler来进行组合,但是在配置上通常代码非常冗余,繁杂;而且不是特别处理,在一些多线程多进程的场景下使用还会导致日中记录混乱的情况出现。
但又这么一个库,它不仅能够减少繁琐的logging配置代码还能实现和logging类似的功能,同时还能保证日志记录线程进程的安全,又能够和logging互相兼容,并进一步追踪异常进行代码回溯。这个库就是叫做Loguru。这个库使用起来非常的简约。
下面就介绍一下Loguru库的使用方法:
1、首先需要安装包 ,安装包需要用到pip,其安装命令为:pip install loguru
2、导入日志记录安装包: from loguru import logger
logger本身就是一个已经实例化好了的对象,如果没有特殊的配置要求,那么自身就已经带有通用的配置参数;同时它的用法和logging标准库输出日志时的用法一致。
例如:
from loguru import logger logger.debug("debug message") logger.info("info level message") logger.warning("warning level message") logger.critical("critical level message")
打印出来显示是这样:
2020-11-30 16:46:23.812 | INFO | other.test_f6:<module>:5 - hello world! 2020-12-01 10:46:22.115 | DEBUG | other.test_f6:<module>:6 - debug message 2020-12-01 10:46:22.115 | INFO | other.test_f6:<module>:7 - info level message 2020-12-01 10:46:22.115 | WARNING | other.test_f6:<module>:8 - warning level message 2020-12-01 10:46:22.115 | CRITICAL | other.test_f6:<module>:9 - critical level message
如果是在IDE或者终端运行时,loguru还会为输出的日志信息带上不同的颜色样式,使信息更加有层次感。
loguru也像logging一样提供了其他可配置的部分,但相比于logging每次都要导入特定的handler再设定一些formatter来说是更为方便。
3、使用loguru配置
使用最基本的logger.add()方法就可以对logger进行简单的配置,这些配置有点类似于使用logging时的handler。
①写入日志
在不指定任何参数时,logger默认采用sys.stderr标准输出将日志输出到控制台中;但是在Linux服务器上有时候不仅输出,还要以文件的形式进行备份,那么只需要在第一个参数中传入一个想要保存文件的路径字符串即可。
实例:
from loguru import logger import os logger.add(os.path.expanduser('testlog.log') logger.info("info message")
如果参数为文件名则直接在当前编辑目录下创建一个log文件,如果为绝对路径则在目标路径下创建log日志文件。
如果拿这段代码跟logging标准库的代码比较的话,可能会显得非常的臃肿。
②日志留存、压缩与清理
一般情况下,如果程序或者重量级的项目,那么可以通过集成的日志平台或数据库来对日志信息进行存储和备份,后面如果有需要用到的地方方便直接拿来分析。
但是对于个人或者中小型项目而言,只需要以文件形式保存输出的日志即可。
如果输出的日志记录时间较长,单个日志文件较大,如果都把日志信息全部写入到一个文件中那么后面我们分析的时候将会非常的恼火,将会变得十分困难。所以我们需要对日志文件进行留存,压缩,在必要的时候进行清理。
可以通过对rotation、compression和retention三个参数设定来满足上面提到的要求(留存、压缩、清理):
rotation 参数能够帮助我们将日志记录以大小、时间等方式进行分割或划分:
import os from loguru import logger log_path = os.path.expanduser(r'../logs') log_filename = os.path.join(log_path, 'file_{time}.log') if os.path.exists(log_path): os.mkdir(log_path) logger.add(log_filename, rotation = "200KB") for i in range(10000): logger.info(f"test- {i}")
这段代码将在当前.py文件的父目录下创建一个名为log目录,下面保存有几个刚刚打印出来的日志文件。
随着分割文件的数量越来越多,就需要对日志进行压缩。使用compression参数,该参数只要传入通用的压缩文件拓展名即可,例如zip、tar、gz等。
只需要将上面的代码add()方法中添加参数 compression = "zip"即可。
logger.add(log_path, rotation = "200KB", compression="zip")
执行完后就可以看到日志文件都被压缩成了zip文件包,有原来的200KB压缩成了10KB,这样对于一些磁盘空间不够的Linux服务器来说是很有必要的。
另外,如果不想对日志进行保存,或者只想保留一段时间内的日志并且对过期的日志进行删除,可以使用参数retention。
同理,只需要在add()方法中,添加retention参数就行了。
logger.add(log_path, rotation="200KB", retention=1)
对retention传入整数类型时,该参数表示所有文件的所以,而非要保留的文件数。
最后我们会看到只有两个时间最近的日志文件被保存下来,其他都被清理掉了。
③序列化
如果在实际应用中不太喜欢以文件的形式保留日志,那么可以通过serialize参数将其转化成序列化的json格式,最后将导入类似于MongoDB、ElasticSearch这类数NoSQL数据库中用作后续的日志分析。
实例:
from loguru import logger import os logger.add(os.path.expanduser("testlog.log"), serialize=True) logger.info("info message")
最后保存的日志都是序列化后的单条记录
2020-12-01 14:38:58.168 | INFO | __main__:<module>:5 - info message
④异常溯源
当异常和错误发生时,最好的方式就是分析日志,查找错误记录。loguru集成了一个名为 batter_exceptions的库,这个库不仅能够将异常和错误记录,并且还能对异常进行溯源。
例如:
import os import sys from loguru import logger logger.add(os.path.expanduser("exception_log.log"), backtrace=True, diagnose=True) def func(a, b): return a / b def nested(c): try: func(5, c) except ZeroDivisionError: logger.exception("what?!") if __name__ = "__main__": nested(0)
运行这段代码会打印出以下内容:
2020-12-01 14:44:10.983 | ERROR | __main__:nested:15 - What?! Traceback (most recent call last): File "C:/Users/admin/Desktop/pythonProject/pyT/other/op.py", line 18, in <module> nested(0) └ <function nested at 0x00000000021A2798> > File "C:/Users/admin/Desktop/pythonProject/pyT/other/op.py", line 13, in nested func(5, c) │ └ 0 └ <function func at 0x00000000021BF798> File "C:/Users/admin/Desktop/pythonProject/pyT/other/op.py", line 9, in func return a / b │ └ 0 └ 5 ZeroDivisionError: division by zero
总的来说loguru算是重新造*,因为有了logging标准库的存在了,但是它能和logging库很好的兼容。loguru有logging库的使用上有许多相似之处,因此在后续 的使用中其实我们就可以将其理解为handler只不过它的范围更加广阔一些,可以除handler之外的字符串、可调用方法、协程对象等。
4、总结
loguru相对于Python内置的logging标准库来说,loguru无疑是更好的选择,因为很多开发者已经为我们一些日常的通用性需求提供了封装好的解决方法,这可以节约很多时间成本。
本文章参考来源于Python中文社区的文章,作者为100gle