Python----logging模块的使用方法

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Python----logging模块的使用方法

【原文链接】

1 logging 日志级别

级别 级别数量 使用场合
DEBUG 10 详细信息,常用语调试
INFO 20 程序正常运行过程中产生的一些信息
WARNING 20 警告用户,虽然程序还在正常工作,但有可能发生错误
ERROR 40 由于更严重的问题,程序已不能执行一些功能了
CRITICAL 50 严重错误,程序已不能继续运行了

2 logging 默认的是warning级别

import logging

logging.debug("this is debug log")
logging.info("this is info log")
logging.warning("this is warning log")
logging.error("this is error log")
logging.critical("this is critical log")

执行结果如下:

WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log

3 可以通过logging.basicConfig(level=logging.DEBUG) 来设置日志级别

import logging

logging.basicConfig(level=logging.DEBUG)
logging.debug("this is debug log")
logging.info("this is info log")
logging.warning("this is warning log")
logging.error("this is error log")
logging.critical("this is critical log")

运行结果如下:

DEBUG:root:this is debug log
INFO:root:this is info log
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log

4 logging日志是一部写入的,logging打印的内容和print打印的内筒先后顺序是不一致的

import logging

print("this is print log")
logging.basicConfig(level=logging.DEBUG)
logging.debug("this is debug log")
logging.info("this is info log")
logging.warning("this is warning log")
logging.error("this is error log")
logging.critical("this is critical log")

运行结果有可能是下面这种输出顺序

DEBUG:root:this is debug log
INFO:root:this is info log
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log
this is print log

5 logging.basicConfig(filename="demo.log")可以指定日志文件名,默认在当前目录下生成文件,此时不再往屏幕打印日志,而是将日志信息输出到指定的日志文件中去

import logging

print("this is print log")
logging.basicConfig(filename="demo.log",level=logging.DEBUG)
logging.debug("this is debug log")
logging.info("this is info log")
logging.warning("this is warning log")
logging.error("this is error log")
logging.critical("this is critical log")

运行后屏幕上输出结果为:

this is print log

而在当前文件下生成了一个demo.log的日志文件,此日志文件的内容为:

DEBUG:root:this is debug log
INFO:root:this is info log
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log

6 logging.basicConfig(filemode='w') 可以指定日志文件的模式,w表示每次清空日志文件,重新写入,a表示在日志文件后面追加,默认的模式为a

将上述 5 中的实例代码再执行一次,demo.log中内容为:

DEBUG:root:this is debug log
INFO:root:this is info log
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log
DEBUG:root:this is debug log
INFO:root:this is info log
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log

若代码修改为如下,再执行:

import logging

print("this is print log")
logging.basicConfig(filename="demo.log",filemode='w',level=logging.DEBUG)
logging.debug("this is debug log")
logging.info("this is info log")
logging.warning("this is warning log")
logging.error("this is error log")
logging.critical("this is critical log")

运行后,demo.log中的内容又恢复到如下内容:

DEBUG:root:this is debug log
INFO:root:this is info log
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log

7 logging 向日志中写入变量的方式

import logging

logging.basicConfig(level=logging.DEBUG)
name="zhangsan"
age=20
logging.debug("name: %s age: %d",name,age)
logging.info("name: %s age: %d" %(name,age))
logging.warning("name: {} age: {}".format(name,age))
logging.error("name: {name} age: {age}".format(name=name,age=age))

运行结果如下:

DEBUG:root:name: zhangsan age: 20
INFO:root:name: zhangsan age: 20
WARNING:root:name: zhangsan age: 20
ERROR:root:name: zhangsan age: 20

8 日志内容格式增加一些公共的内容

import logging

logging.basicConfig(format=("%(asctime)s | %(levelname)s | %(filename)s:%(lineno)s | %(message)s"),
                    datefmt="%Y-%m-%d_%H:%M:%S",
                    level=logging.DEBUG)
name="zhangsan"
age=20
logging.debug("name: %s age: %d",name,age)
logging.info("name: %s age: %d" %(name,age))
logging.warning("name: {} age: {}".format(name,age))
logging.error("name: {name} age: {age}".format(name=name,age=age))

运行结果为:

2020-08-03_07:20:42 | DEBUG | test1.py:9 | name: zhangsan age: 20
2020-08-03_07:20:42 | INFO | test1.py:10 | name: zhangsan age: 20
2020-08-03_07:20:42 | WARNING | test1.py:11 | name: zhangsan age: 20
2020-08-03_07:20:42 | ERROR | test1.py:12 | name: zhangsan age: 20

9 logging的高级应用

logging模块采用了模块化设计,主要包含四种组件

  • Loggers:记录器,提供应用程序代码能直接使用的接口
  • Handlers:处理器,将记录器产生的日志发送到目的地
  • Filters:过滤器,提供更好的粒度控制,决定哪些日志会被输出
  • 格式化器:设置内置内容的组成结构和消息字段

10 logging的高级应用流程


                             |---创建屏幕StreamHandler--设置日志等级---|
创建一个logger并设置默认等级---|                                       |----创建formatter----用formatter渲染所有的hansdler----将所有的handler加入logger内----程序调用logger
                             |---创建文件FileHandler--设置日志等级-----|

11 loggers记录器

  • 提供应用程序的调用接口

    logger=logging。getLogger(__name__)
    logger是单例的

  • 决定日志记录的级别

    logger.setLevel()

  • 将日志内容传递到相关联的handlers中

    logger.addHandler()

    logger。removeHandler()

12 handler处理器

  • StreamHandler

    标准输出stdout(如显示器)分发器

    创建方法: sh=logging.StreamHandler(stream=None)

  • FileHandler

    将日志保存到磁盘文件的处理器

    创建方法:fh=logging.FileHandler(filename,mode="a",enconding=None,delay=False)

  • setFormatter(): 设置当前handler对象使用的消息格斯

13 常用的Handlers处理器

  • StreamHandler
  • FileHandler
  • BaseRotatingHandler
  • RotatingHandler
  • TimedRotatingFileHandler
  • SocketHandler
  • DatagramHandler
  • SMTPHandler
  • SysLogHandler
  • NTEventLogHandler
  • HTTPHandler
  • WatchedFileHandler
  • QueueHandler
  • NullHandler

14 常见的formatter格式

属性 格式 描述
asctime %(asctime)s 日志产生的时间,默认格式为2020-08-03 12.12.12,265
created %(created)f time.time()生成的日志创建时间戳
filename %(filename)s 生成日志的程序名
funcName %(funcName)s 调用日志的函数名
levelname %(levelname)s 日志级别(DEBUG,INFO,WARNING,ERROR,CRITICAL)
levelno %(levelno)s 日志级别对应的数值
lineno %(lineno)s) 日志所针对的代码行号(如果可用的话)
module %(module)s 生成日志的模块名
mesecs %(mesecs)d 日志生成的时间的毫秒部分
message %(message)s 具体的日志信息
name %(name)s 日志调用者
pathname %(pathname)s 生成日志的文件的完整路径
process %(process)d 生成日志的进程id(如果可用)
processName %(processName)s 进程名(如果可用)
thread %(thread)d 生成日志的线程id(如果可用)
threadName %(threadName)s 线程名(如果可用)

15 下面两段代码的功能是完全一样的,使用logging直接调info、debug等日志与实例化一个默认的root logger是一样的,换言之,使用logging直接调日志方法的方式就是通过获取root日志来实现的

import logging

logging.debug("this is debug log")
logging.info("this is info log")
logging.warning("this is warning log")
logging.error("this is error log")
logging.critical("this is critical log")

logger=logging.getLogger()
logger.debug("this is debug log")
logger.info("this is info log")
logger.warning("this is warning log")
logger.error("this is error log")
logger.critical("this is critical log"

运行结果如下:

WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log

16 下面一段代码使用getLogger时指定一个名称,即实例化一个logger,然后设置两种处理器,分别往控制台和文件中写日志,还可以设置日志内容的格式,具体如下所示

import logging


logger=logging.getLogger("test")

console_handler=logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)

file_handler=logging.FileHandler(filename="demo.log")
file_handler.setLevel(logging.DEBUG)

formatter=logging.Formatter(fmt="%(asctime)s | %(levelname)s | %(filename)s:%(lineno)s | %(message)s")

console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)

logger.addHandler(console_handler)
logger.addHandler(file_handler)

log=logger

log.debug("this is debug log")
log.info("this is info log")
log.warning("this is warning log")
log.error("this is error log")
log.critical("this is critical log")

运行结果如下:

2020-08-04 23:08:56,625 | WARNING | test1.py:25 | this is warning log
2020-08-04 23:08:56,625 | ERROR | test1.py:26 | this is error log
2020-08-04 23:08:56,625 | CRITICAL | test1.py:27 | this is critical log

并且在demo.log日志文件中写入了如下内容:

2020-08-04 23:08:56,625 | WARNING | test1.py:25 | this is warning log
2020-08-04 23:08:56,625 | ERROR | test1.py:26 | this is error log
2020-08-04 23:08:56,625 | CRITICAL | test1.py:27 | this is critical log

17 上述 16 的日志打印明显与本来的期望是不一致的,本来期望控制台和文件都是设置了DEBUG级别,但实际上控制台和文件中都打印了Warning的级别的日志

这里需要注意的是,logger默认的日志级别是warning,而日志的最终级别将取决于logger和handler级别的最高级别,所以上述16中虽然控制台和文件handler的日志级别都设置了debug,但是因为logger默认级别是warning,所以最终打印的都是warning级别,下面一段代码将logger设置为debug级别,然后将控制台设置为info,将文件handler设置为warning,然后再看一下效果:

import logging


logger=logging.getLogger("test")
logger.setLevel(logging.DEBUG)

console_handler=logging.StreamHandler()
console_handler.setLevel(logging.INFO)

file_handler=logging.FileHandler(filename="demo.log")
file_handler.setLevel(logging.WARNING)

formatter=logging.Formatter(fmt="%(asctime)s | %(levelname)s | %(filename)s:%(lineno)s | %(message)s")

console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)

logger.addHandler(console_handler)
logger.addHandler(file_handler)

log=logger

log.debug("this is debug log")
log.info("this is info log")
log.warning("this is warning log")
log.error("this is error log")
log.critical("this is critical log")

运行结果如下:

2020-08-04 23:21:37,888 | INFO | test1.py:25 | this is info log
2020-08-04 23:21:37,888 | WARNING | test1.py:26 | this is warning log
2020-08-04 23:21:37,888 | ERROR | test1.py:27 | this is error log
2020-08-04 23:21:37,888 | CRITICAL | test1.py:28 | this is critical log

而在demo.log日志文件中写入了如下内容,此时与上述分析一致了

2020-08-04 23:21:37,888 | WARNING | test1.py:26 | this is warning log
2020-08-04 23:21:37,888 | ERROR | test1.py:27 | this is error log
2020-08-04 23:21:37,888 | CRITICAL | test1.py:28 | this is critical log

18 定义filter并给控制台的handler加一个filter,过滤的name与日志名称不一致,如下代码,此时则不会往控制台写日志,但日志文件的日志还是正常写的

import logging


logger=logging.getLogger("test")
logger.setLevel(logging.DEBUG)

console_handler=logging.StreamHandler()
console_handler.setLevel(logging.INFO)

file_handler=logging.FileHandler(filename="demo.log")
file_handler.setLevel(logging.WARNING)

formatter=logging.Formatter(fmt="%(asctime)s | %(levelname)s | %(filename)s:%(lineno)s | %(message)s")

console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)

logger.addHandler(console_handler)
logger.addHandler(file_handler)

filter=logging.Filter("test1")
console_handler.addFilter(filter)

log=logger

log.debug("this is debug log")
log.info("this is info log")
log.warning("this is warning log")
log.error("this is error log")
log.critical("this is critical log")

此时运行后控制台结果为空,日志文件如下日志打印正常

2020-08-04 23:31:00,459 | WARNING | test1.py:29 | this is warning log
2020-08-04 23:31:00,459 | ERROR | test1.py:30 | this is error log
2020-08-04 23:31:00,459 | CRITICAL | test1.py:31 | this is critical log

19 配置文件的方式

  • (1) 首先编写类似如下的log配置文件:logging.conf, 这里面定义了root和test两个logger
[loggers]
keys=root,test

[handlers]
keys=fileHandler,consoleHandler

[formatters];
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_test]
level=DEBUG
handlers=fileHandler,consoleHandler
qualname=test
propagate=0

[handler_consoleHandler]
class=StreamHandler
args=(sys.stdout,)
level=DEBUG
formatter=simpleFormatter

[handler_fileHandler]
class=handlers.TimedRotatingFileHandler
args=("test.log","midnight",1,0)
level=DEBUG
formatter=simpleFormatter

[formatter_simpleFormatter]
format=%(asctime)s|%(levelname)s|%(filename)s[line:%(lineno)d]|%(message)s
datafmt=%Y-%m-%d_%H:%M:%S
  • (2)然后在py文件中编写如下代码,这里演示了root的logger和test的logger两种的使用方式

import logging.config

logging.config.fileConfig("logging.conf")
logger=logging.getLogger("test")

log=logger
log.debug("this is debug log")
log.info("this is info log")
log.warning("this is warning log")
log.error("this is error log")
log.critical("this is critical log")

rlog=logging.getLogger("root")
rlog.debug("this is debug log")
rlog.info("this is info log")
rlog.warning("this is warning log")
rlog.error("this is error log")
rlog.critical("this is critical log")

运行结果如下:

2020-08-05 00:25:02,673|DEBUG|test1.py[line:8]|this is debug log
2020-08-05 00:25:02,674|INFO|test1.py[line:9]|this is info log
2020-08-05 00:25:02,674|WARNING|test1.py[line:10]|this is warning log
2020-08-05 00:25:02,674|ERROR|test1.py[line:11]|this is error log
2020-08-05 00:25:02,674|CRITICAL|test1.py[line:12]|this is critical log
2020-08-05 00:25:02,674|DEBUG|test1.py[line:15]|this is debug log
2020-08-05 00:25:02,674|INFO|test1.py[line:16]|this is info log
2020-08-05 00:25:02,674|WARNING|test1.py[line:17]|this is warning log
2020-08-05 00:25:02,674|ERROR|test1.py[line:18]|this is error log
2020-08-05 00:25:02,674|CRITICAL|test1.py[line:19]|this is critical log

同时在test.log日志文件中生成如下日志:

2020-08-05 00:25:02,673|DEBUG|test1.py[line:8]|this is debug log
2020-08-05 00:25:02,674|INFO|test1.py[line:9]|this is info log
2020-08-05 00:25:02,674|WARNING|test1.py[line:10]|this is warning log
2020-08-05 00:25:02,674|ERROR|test1.py[line:11]|this is error log
2020-08-05 00:25:02,674|CRITICAL|test1.py[line:12]|this is critical log

20 在上述19的基础上,加入在其他文件中想使用建好的log系统进行日志的打印,有如下两种使用方法:

import test1
import logging


log=logging.getLogger("test")

log.debug("this is debug log")
log.info("this is info log")
log.warning("this is warning log")
log.error("this is error log")
log.critical("this is critical log")

log=test1.logger

log.debug("this is debug log")
log.info("this is info log")
log.warning("this is warning log")
log.error("this is error log")
log.critical("this is critical log")

运行结果如下:

2020-08-05_00:31:35|DEBUG|test2.py[line:8]|this is debug log
2020-08-05_00:31:35|INFO|test2.py[line:9]|this is info log
2020-08-05_00:31:35|WARNING|test2.py[line:10]|this is warning log
2020-08-05_00:31:35|ERROR|test2.py[line:11]|this is error log
2020-08-05_00:31:35|CRITICAL|test2.py[line:12]|this is critical log
2020-08-05_00:31:35|DEBUG|test2.py[line:16]|this is debug log
2020-08-05_00:31:35|INFO|test2.py[line:17]|this is info log
2020-08-05_00:31:35|WARNING|test2.py[line:18]|this is warning log
2020-08-05_00:31:35|ERROR|test2.py[line:19]|this is error log
2020-08-05_00:31:35|CRITICAL|test2.py[line:20]|this is critical log

日志文件中也生成了对应的日志:

2020-08-05_00:31:35|DEBUG|test2.py[line:8]|this is debug log
2020-08-05_00:31:35|INFO|test2.py[line:9]|this is info log
2020-08-05_00:31:35|WARNING|test2.py[line:10]|this is warning log
2020-08-05_00:31:35|ERROR|test2.py[line:11]|this is error log
2020-08-05_00:31:35|CRITICAL|test2.py[line:12]|this is critical log
2020-08-05_00:31:35|DEBUG|test2.py[line:16]|this is debug log
2020-08-05_00:31:35|INFO|test2.py[line:17]|this is info log
2020-08-05_00:31:35|WARNING|test2.py[line:18]|this is warning log
2020-08-05_00:31:35|ERROR|test2.py[line:19]|this is error log
2020-08-05_00:31:35|CRITICAL|test2.py[line:20]|this is critical log

21 在try - except语句块中,打印异常日志可以使用log.exception(e),这个函数可以将程序错误调用栈打印出来

import logging.config

logging.config.fileConfig("logging.conf")
logger=logging.getLogger("test")

log=logger

try:
    a=1/0
except Exception as e:
    log.exception(e)

运行结果如下:

2020-08-05_00:35:14|ERROR|test1.py[line:12]|division by zero
Traceback (most recent call last):
  File "G:/lamb_source/test/log/test1.py", line 10, in <module>
    a=1/0
ZeroDivisionError: division by zero
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
2月前
|
开发者 Python
如何在Python中管理模块和包的依赖关系?
在实际开发中,通常会结合多种方法来管理模块和包的依赖关系,以确保项目的顺利进行和可维护性。同时,要及时更新和解决依赖冲突等问题,以保证代码的稳定性和可靠性
57 4
|
19天前
|
Python
Python Internet 模块
Python Internet 模块。
118 74
|
2月前
|
算法 数据安全/隐私保护 开发者
马特赛特旋转算法:Python的随机模块背后的力量
马特赛特旋转算法是Python `random`模块的核心,由松本真和西村拓士于1997年提出。它基于线性反馈移位寄存器,具有超长周期和高维均匀性,适用于模拟、密码学等领域。Python中通过设置种子值初始化状态数组,经状态更新和输出提取生成随机数,代码简单高效。
118 63
|
2月前
|
测试技术 Python
手动解决Python模块和包依赖冲突的具体步骤是什么?
需要注意的是,手动解决依赖冲突可能需要一定的时间和经验,并且需要谨慎操作,避免引入新的问题。在实际操作中,还可以结合使用其他方法,如虚拟环境等,来更好地管理和解决依赖冲突😉。
|
2月前
|
持续交付 Python
如何在Python中自动解决模块和包的依赖冲突?
完全自动解决所有依赖冲突可能并不总是可行,特别是在复杂的项目中。有时候仍然需要人工干预和判断。自动解决的方法主要是提供辅助和便捷,但不能完全替代人工的分析和决策😉。
|
2月前
|
JSON Linux 数据格式
Python模块:从入门到精通,只需一篇文章!
Python中的模块是将相关代码组织在一起的单元,便于重用和维护。模块可以是Python文件或C/C++扩展,Python标准库中包含大量模块,如os、sys、time等,用于执行各种任务。定义模块只需创建.py文件并编写代码,导入模块使用import语句。此外,Python还支持自定义模块和包,以及虚拟环境来管理项目依赖。
Python模块:从入门到精通,只需一篇文章!
|
2月前
|
监控 开发者 Python
Python 默认 `logging` 打印级别详解
本文详细介绍了 Python `logging` 模块的默认打印级别及其配置方法。`logging` 模块支持 `DEBUG`、`INFO`、`WARNING`、`ERROR` 和 `CRITICAL` 五个日志级别,默认级别为 `WARNING`。文章通过示例代码展示了如何设置和使用不同日志级别,并介绍了进一步的配置选项,如日志格式和文件输出。
59 8
|
2月前
|
Python
Python的模块和包
总之,模块和包是 Python 编程中非常重要的概念,掌握它们可以帮助我们更好地组织和管理代码,提高开发效率和代码质量
45 5
|
2月前
|
数据可视化 Python
如何在Python中解决模块和包的依赖冲突?
解决模块和包的依赖冲突需要综合运用多种方法,并且需要团队成员的共同努力和协作。通过合理的管理和解决冲突,可以提高项目的稳定性和可扩展性
|
2月前
|
Python
在Python中,可以使用内置的`re`模块来处理正则表达式
在Python中,可以使用内置的`re`模块来处理正则表达式
60 5