测试开发技术网站
博客
设计
设计
开发
Python
测试
unittest
运维
Linux基础应用
CI/CD
CI/CD
数据库
数据库
云计算
云计算
云原生
云原生
爬虫
爬虫
数据分析
数据分析
人工智能
人工智能
登录
注册
Python如何写日志即logging日志模块的使用方法
收藏本文
作者:redrose2100 类别: 日期:2022-05-10 09:33:25 阅读:853 次 消耗积分:0 分
### 1 logging 日志级别 |级别|级别数量|使用场合| |:---|:---|:---| |DEBUG|10|详细信息,常用语调试| |INFO|20|程序正常运行过程中产生的一些信息| |WARNING|20|警告用户,虽然程序还在正常工作,但有可能发生错误| |ERROR|40|由于更严重的问题,程序已不能执行一些功能了| |CRITICAL|50|严重错误,程序已不能继续运行了| ### 2 logging 默认的是warning级别 ```python 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") ``` 执行结果如下: ```python WARNING:root:this is warning log ERROR:root:this is error log CRITICAL:root:this is critical log ``` ### 3 可以通过logging.basicConfig(level=logging.DEBUG) 来设置日志级别 ```python 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") ``` 运行结果如下: ```python 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打印的内筒先后顺序是不一致的 ```python 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") ``` 运行结果有可能是下面这种输出顺序 ```python 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")可以指定日志文件名,默认在当前目录下生成文件,此时不再往屏幕打印日志,而是将日志信息输出到指定的日志文件中去 ```python 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") ``` 运行后屏幕上输出结果为: ```python this is print log ``` 而在当前文件下生成了一个demo.log的日志文件,此日志文件的内容为: ```python 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中内容为: ```python 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 ``` 若代码修改为如下,再执行: ```python 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中的内容又恢复到如下内容: ```python 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 向日志中写入变量的方式 ```python 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)) ``` 运行结果如下: ```python 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 日志内容格式增加一些公共的内容 ```python 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)) ``` 运行结果为: ```pyhton 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的高级应用流程 ```python |---创建屏幕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日志来实现的 ```python 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" ``` 运行结果如下: ```python 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,然后设置两种处理器,分别往控制台和文件中写日志,还可以设置日志内容的格式,具体如下所示 ```pyhton 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") ``` 运行结果如下: ```python 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日志文件中写入了如下内容: ```python 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,然后再看一下效果: ```python 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") ``` 运行结果如下: ```python 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日志文件中写入了如下内容,此时与上述分析一致了 ```python 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与日志名称不一致,如下代码,此时则不会往控制台写日志,但日志文件的日志还是正常写的 ```python 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") ``` 此时运行后控制台结果为空,日志文件如下日志打印正常 ```python 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 ```python [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两种的使用方式 ```python 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") ``` 运行结果如下: ```python 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日志文件中生成如下日志: ```python 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系统进行日志的打印,有如下两种使用方法: ```python 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") ``` 运行结果如下: ```python 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 ``` 日志文件中也生成了对应的日志: ```python 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),这个函数可以将程序错误调用栈打印出来 ```python 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) ``` 运行结果如下: ```python 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
a=1/0 ZeroDivisionError: division by zero ```
始终坚持开源开放共享精神,同时感谢您的充电鼓励和支持!
版权所有,转载本站文章请注明出处:redrose2100, http://blog.redrose2100.com/article/143
上一篇:
Python基础入门----Python简介
下一篇:
Python如何处理编码即chardet模块的使用方法
搜索
个人成就
出版书籍
《Pytest企业级应用实战》
测试开发技术全栈公众号
测试开发技术全栈公众号
DevOps技术交流微信群
加微信邀请进群
常用网站链接
开源软件洞察
云原生技术栈全景图
Python语言官方文档
Golang官方文档
Docker官方文档
Jenkins中文用户手册
Scrapy官方文档
VUE官方文档
Harbor官方文档
openQA官方文档
云原生开源社区
开源中国
Kubernetes中文文档
Markdown语法官方教程
Kubernetes中文社区
Kubersphere官方文档
BootStrap中文网站
JavaScript中文网
NumPy官方文档
Pandas官方文档
GitLink确实开源网站
数据库排名网站
编程语言排名网站
SEO综合查询网站
数学加减法练习自动生成网站
Kickstart Generator
文章分类
最新文章
最多阅读
特别推荐
×
Close
登录
注册
找回密码
登录邮箱:
登录密码:
图片验证码:
注册邮箱:
注册密码:
邮箱验证码:
发送邮件
注册邮箱:
新的密码:
邮箱验证码:
发送邮件