Python-logging模块实现同时向控制台和文件打印日志
Python-logging模块实现同时向控制台和文件打印日志
前言
在写我自己的练手项目的时候,需要写一系列Python脚本来帮助我进行运维/环境配置,我希望这些脚本能够有比较好的日志记录。
一方面我希望其能够直接打印到控制台,方便我实时查看,另一方面我也希望能够记录到日志文件中,这样能够方便我日后翻旧账。
更进一步,我希望控制台输出比较重要的信息,让我的控制台不至于太乱,而日志文件中我希望能够尽量详细。
参考
basicConfig
参考Python 官方文档 | logging模块#basicConfig
这个函数对logging模块的日志记录器进行基本配置,无论我们直接通过logging.info(msg)
进行日志记录,还是我们先通过logging.getLogger(name)
获取一个logger再进行日志记录,通过basicConfig
函数加入的配置都会生效。
值得注意的是,因为有些操作会导致basicConfig
函数被自动调用,所以我们尽量在程序开始时尽早进行调用。
我们需要关注的是basicConfig
的handlers
参数。
handler
如果说logger是面向上层开发者的接口,那么handler就是面向底层的执行者。开发者通过调用logger的方法来输出日志,而logger通过handler将日志进行实际的记录。
一个logger可以有若干handler,logger和handler都可以有一个日志等级。当记录等级高于logger的日志时,logger会通知每一个handler对该日志进行记录,而每一个handler记录会通过该条日志的等级和handler的等级进行比较,当日志等级高于handler等级的时候,才会进行记录。
handler主要位于logging.handler包下,我们这次需要使用StreamHandler
以及其子类FileHandler
。
实现
通过前面的分析,思路已经很清晰了:
- 创建两个handler,其中一个向控制台进行输出,一个向文件进行输出;
- 为这两个handler配置不同的日志等级和日志格式;
- 通过
basicConfig
函数来将这两个handler添加到全局日志的默认配置;
以下为实现:
import logging
import sys
def config_logging(file_name: str, console_level: int=logging.INFO, file_level: int=logging.DEBUG):
file_handler = logging.FileHandler(file_name, mode='a', encoding="utf8")
file_handler.setFormatter(logging.Formatter(
'%(asctime)s [%(levelname)s] %(module)s.%(lineno)d %(name)s:\t%(message)s')
)
file_handler.setLevel(file_level)
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(logging.Formatter(
'[%(asctime)s %(levelname)s] %(message)s',
datefmt="%Y/%m/%d %H:%M:%S")
)
console_handler.setLevel(console_level)
logging.basicConfig(
level=min(console_level, file_level),
handlers=[file_handler, console_handler],
)
if __name__ == '__main__':
config_logging("test.log", logging.WARNING, logging.DEBUG)
logging.debug("debug")
logging.info("info")
logging.warning("warning")
logging.critical("critical")
logger = logging.getLogger(__name__)
logger.debug("debug")
logger.info("info")
logger.warning("warning")
logger.critical("critical")
关键是config_logging
函数,这个函数进行了基本的配置,我们只需要在程序的入口处先调用这个函数就能完成全局的日志配置。
需要注意的是在调用logging.basicConfig
时,我们需要设置level=min(console_level, file_level)
,这是因为这个参数设置的是logger的等级,如果一条日志已经被logger过滤掉了,那么handler的等级设置的再低也不会进行记录。直接level=logging.DEBUG
、level=0
应该也可以,但是我认为比所有handler的等级都低的日志是不会进行输出的,与其让这条日志到了handler这一步才被过滤,不如直接就在logger这一步就将其过滤掉。
原文地址:https://www.cnblogs.com/SnowPhoenix/p/15201097.html
- 运维中的日志切割操作梳理(Logrotate/python/shell脚本实现)
- 线上图片批量更换脚本记录
- memcached程序端口监控脚本
- mysql操作命令梳理(5)-执行sql语句查询即mysql状态说明
- 【7】AccessDB快速数据访问
- 4.微信支付
- 【8】数据浏览表格的快速输出
- Silverlight的自定义tooltip提示工具条
- WritableBitmapEx 一瞥
- 2.认证小程序
- 【9】分页浏览的管理
- 温故而知新:silverlight中的图片资源绑定
- 页面状态保持机制(编辑中)
- mysql主从同步(5)-同步延迟状态考量(seconds_behind_master和pt-heartbea)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法