Python之打印日志库(logging)
作者:hopyGreat
一、日志等级
级别 | 何时使用 |
---|---|
DEBUG | 细节信息,仅当诊断问题时使用 |
INFO | 确认程序按预期运行 |
WARNING | 表明已经或即将发生的意外(例如:磁盘空间不足)。程序仍按预期进行 |
ERROR | 由于严重的问题,程序的某些功能已经不能正常执行 |
CRITICAL | 严重的错误,表明程序已不能继续执行 |
默认等级是“WARNING”,意味着只会跟踪该级别及以上的事件(由上倒下等级以此递增),除非更改日志配置。
二、基本用法
1. quick start
>>> import logging >>> logging.warning("warning") WARNING:root:warning >>> logging.info("information") >>>
注意这里只有warning的信息打印出来了。如前面所说,默认等级是“WARNING”,只会追踪该级别及以上的事件,所以info信息没有被打印出来。
其中WARNING是记录级别;root代表打印的模块来源(没有显示设置,显然是默认值,甚至不是当前模块的名称);warning就是我们显示打印的数据信息了。
2. 记录日志到文件
import logging logging.basicConfig(filename='pycode.log', level=logging.DEBUG) logging.warning('warning') logging.info('information') logging.debug('debug')
通过设置logging的基本配置可以将记录重定向到文件中。同时可以通过level指定打印级别。
# pycode.log WARNING:root:warning INFO:root:information DEBUG:root:debug
注意到,此时在文件中的打印级别已经降为 DEBUG了。该方法也适用在命令行中修改打印级别。
但有个需要注意的点:对basicConfig的调用应该在debug(),info()等函数前面。basicConfig是一次性的配置,只有第一次调用会进行操作,随后的调用不会产生有效操作。
什么意思呢?
举个例子:
>>> import logging >>> logging.warning("123") WARNING:root:123 >>> logging.info("123") # 不会有输出 >>> logging.basicConfig(level=logging.DEBUG) >>> logging.info("123") # 依旧不会有输出
另一个例子:
>>> import logging >>> logging.basciConfig(level=loggin.DEBUG) >>> logging.warning("123") WARNING:root:123 >>> logging.info("123") INFO:root:123
在第一次调用logging.info()、warning()等函数的时候,就会调用内置的basicConfig。此时就已经固化打印级别为WARNING了,即使后面再次显式调用basicConfig也不会有效。
命令行指定级别:除了通过basicConfig设置level,也可以在执行Python程序的时候,通过命令行参数指定。
$ 设置logging打印级别为INFO $ python3 pycode.py --log=INFO
追加打印:此外,记录输出到文件中,默认是追加打印的。如果希望重新记录,可以这样:
logging.basicConfig(filename='pycode.log', filemode='w', level=logging.DEBUG)
3. 多模块打印
# main.py import logging import somelib logging.basicConfig(level=logging.INFO) def main(): logging.info("py01") py02.do_something() if __name__ == '__main__': main() # --------------------------- # somelib.py import logging def do_something(): logging.info("py02")
输出:
# pycode.log
INFO:root:py01
INFO:root:py02
可以看到,多模块的信息都能正常打印到日志文件中。但很明显可以发现不论是从哪个模块输出,日志记录中显示的都是root。所以目前还不能跟踪记录打印的模块来源。
4. 定义打印格式
前面出现的打印信息基本上是:记录级别:模块来源:记录信息
同样可以在basicConfig中定义打印的格式:
>>> import logging >>> logging.basicConfig(format='%(asctime)s : %(name)s : %(message)s', level=logging.INFO) >>> logging.info("123") 2020-06-19 22:38:16,048 : root : 123
可以看到,此时展示了打印时间,模块来源及记录信息。
格式配置属性:
格式 | 描述 |
---|---|
%(asctime)s | 调用消息记录打印时的时间(格式化后的时间) |
%(created)f | 调用消息记录打印时的时间(未格式化的描述,相当于time.time()) |
%(filename)s | 调用消息记录打印的文件名称(在哪个文件里面) |
%(funcName)s | 调用消息记录打印的函数名称(在哪个函数里面) |
%(levelname)s | 消息记录级别(DEBUG,INFO,WARNING,ERROR,CRITICAL) |
%(levelno)s | 消息记录级别的数字号(DEBUG=10,INFO=20,WARNING=30,ERROR=40,CRITICAL=50) |
%(lineno)d | 调用消息记录打印的行数(在哪一行打印的) |
%(message)s | 待打印的自定义消息 |
%(module)s | 调用消息记录的模块名 |
%(msecs)d | 调用消息记录打印时间的毫秒部分 |
%(name)s | 打印消息的logger对象名称(自定义的,默认是root) |
%(pathname)s | 调用消息记录的文件路径 |
%(process)d | 进程ID |
%(processName)s | 进程名 |
%(relativeCreated)d | 相对logging模块被加载到打印消息记录时的相对时间(毫秒) |
%(thread)d | 线程ID |
%(threadName)s | 线程名 |
此时,为了跟踪打印消息的来源,我们可以组织一个这样的格式串:
# main.py import logging import somelib logging.basicConfig( level=logging.INFO, format="%(asctime)s: %(name)s: %(levelname)s: %(message)s") logger = logging.getLogger("main123") def main(): logger.info("py01") somelib.do_something() if __name__ == '__main__': main() # ------------------------------ # somelib.py import logging logger = logging.getLogger("pylib") def do_something(): logger.info("py02") # ------------------------------ # 输出 2020-06-19 23:26:27,263: main123: INFO: py01 2020-06-19 23:26:27,264: pylib: INFO: py02
有其他的需求,也可以根据上面列出来的属性自行搭配。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。