python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python打印日志库

Python之打印日志库(logging)

作者:hopyGreat

这篇文章主要介绍了Python之打印日志库(logging),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、日志等级

级别何时使用
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

有其他的需求,也可以根据上面列出来的属性自行搭配。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文