Python logging系统
我们都知道python在2.x之后自带了一个模块import logging.
但是每次都要写log很麻烦,同时我想把info,debug之类的指令通过颜色分离开来。
于是写了一个简单的类似glog的小程序(完善是不可能完善的,checkeq这辈汁都不可能写的)
import logging
from colorlog import ColoredFormatter
import sys
import os def currentframe():
"""Return the frame object for the caller's stack frame."""
try:
raise Exception
except:
return sys.exc_info()[2].tb_frame.f_back
_srcfile = os.path.normcase(currentframe.__code__.co_filename) logging._srcfile = _srcfile class myLogger(logging.Logger):
def __init__(self):
super(myLogger, self).__init__('my_logger')
formatter = ColoredFormatter(
"%(asctime)s - %(filename)s - [line:%(lineno)d] - %(log_color)s%(levelname)s: %(white)s%(message)s",
datefmt = None,
reset = True,
log_colors = {
'DEBUG': 'cyan',
'INFO': 'green',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'red',
}
) self.logger = logging.getLogger('example')
handler = logging.StreamHandler()
handler.setFormatter(formatter)
self.logger.addHandler(handler)
self.logger.setLevel(logging.DEBUG) def setLevel(self, opt):
self.logger.setLevel(opt) def log(self, opt, str):
if opt == 'debug':
self.logger.debug(str)
if opt == 'info':
self.logger.info(str)
if opt == 'warning':
self.logger.warning(str)
if opt == 'error':
self.logger.error(str)
if opt == 'critical':
self.logger.critical(str) def log_if(self, opt, flag, str):
if (flag == True):
self.log(opt, str) def debug(self, str):
self.logger.debug(str) def debug_if(self, flag, str):
if (flag == True):
self.logger.debug(str) def info(self, str):
self.logger.info(str) def info_if(self, flag, str):
if (flag == True):
self.logger.info(str) def warning(self, str):
self.logger.warning(str) def warning_if(self, flag, str):
if (flag == True):
self.logger.warning(str) def error(self, str):
self.logger.error(str) def error_if(self, flag, str):
if (flag == True):
self.logger.error(str) def critical(self, str):
self.logger.critical(str) def critical_if(self, flag, str):
if (flag == True):
self.logger.critical(str)
myLogger
还有一个demo
import logging
from myLogger import myLogger def demo():
log = myLogger()
log.log('debug', 'log debug test') log.log_if('info', True, 'log_if info test')
log.log('warning', 'log warning test')
log.log_if('warning', False, 'log_if warning test')
log.log_if('error', True, 'log_if error test')
log.log('critical', 'log critical test') print(' ') log.debug('log debug function test')
log.info('log info function test')
log.warning('log warning function test')
log.error('log error function test')
log.critical('log critical function test') print(' ') log.setLevel(logging.WARNING)
log.info('log info function test set level')
log.warning('log warning function test set level')
log.error_if(True, 'log error if true')
log.critical_if(False, 'log critical if false') if __name__ == '__main__':
demo()
myLoggerDemo
效果就如下图:

下面稍微解释一下python的logging的原理:
我们以python2.7的logging模块为例子:
先查看logging最开始的一个函数currentframe():
# next bit filched from 1.5.2's inspect.py
def currentframe():
"""Return the frame object for the caller's stack frame."""
try:
raise Exception
except:
return sys.exc_info()[2].tb_frame.f_back
这个函数的作用就是获得当前函数(caller)的在内存中的栈帧。
那么这个函数有什么用的呢?
下面还有一句话:
# _srcfile is used when walking the stack to check when we've got the first
# caller stack frame.
#
_srcfile = os.path.normcase(currentframe.__code__.co_filename)
通过currentframe()的信息,就能获得_srcfile,也就是这个python_root/lib/logging/__init__.py的filename。
而我们在import logging之后,例如通过log.info(),希望获得当前的filename,logging是怎么做的呢?
在logging/__init__.py中的class Logger(Filterer)中有一个函数findCaller():
def findCaller(self):
"""
Find the stack frame of the caller so that we can note the source
file name, line number and function name.
"""
f = currentframe()
#On some versions of IronPython, currentframe() returns None if
#IronPython isn't run with -X:Frames.
if f is not None:
f = f.f_back
rv = "(unknown file)", 0, "(unknown function)"
while hasattr(f, "f_code"):
co = f.f_code
filename = os.path.normcase(co.co_filename)
if filename == _srcfile:
f = f.f_back
continue
rv = (co.co_filename, f.f_lineno, co.co_name)
break
return rv
显然这个函数的作用就是先获得当前这个findCaller的栈帧,然后不断地回退,一直到栈帧的文件信息不是当前logging/__init__.py为止,这时候就是我调用log.info()的具体位置了。
所以为了添加彩色弹幕信息,我们在新加一个myLogger类的时候,记得把logging中的_srcfile从python_root/lib/logging/__init__.py换成当前文件就好了,替换的方法和logging本身如出一辙。
至此我们理解和改造python log告一段落,但是glog的checkeq我是坚决不会写的(因为不会)。
Python logging系统的更多相关文章
- Python logging日志系统
写我小小的日志系统 配置logging有以下几种方式: 1)使用Python代码显式的创建loggers, handlers和formatters并分别调用它们的配置函数: 2)创建一个日志配置文件, ...
- python logging模块可能会令人困惑的地方
python logging模块主要是python提供的通用日志系统,使用的方法其实挺简单的,这块就不多介绍.下面主要会讲到在使用python logging模块的时候,涉及到多个python文件的调 ...
- Python LOGGING使用方法
Python LOGGING使用方法 1. 简介 使用场景 场景 适合使用的方法 在终端输出程序或脚本的使用方法 print 报告一个事件的发生(例如状态的修改) logging.info()或log ...
- Python logging 模块和使用经验
记录下常用的一些东西,每次用总是查文档有点小麻烦. py2.7 日志应该是生产应用的重要生命线,谁都不应该掉以轻心 有益原则 级别分离 日志系统通常有下面几种级别,看情况是使用 FATAL - 导致程 ...
- python logging模块使用流程
#!/usr/local/bin/python # -*- coding:utf-8 -*- import logging logging.debug('debug message') logging ...
- python logging详解及自动添加上下文信息
之前写过一篇文章日志的艺术(The art of logging),提到了输出日志的时候记录上下文信息的重要性,我认为上下文信息包括: when:log事件发生的时间 where:log事件发生在哪个 ...
- python logging模块使用教程
简单使用 #!/usr/local/bin/python # -*- coding:utf-8 -*- import logging logging.debug('debug message') lo ...
- 0x01 Python logging模块
目录 Python logging 模块 前言 logging模块提供的特性 logging模块的设计过程 logger的继承 logger在逻辑上的继承结构 logging.basicConfig( ...
- python logging 配置
python logging 配置 在python中,logging由logger,handler,filter,formater四个部分组成,logger是提供我们记录日志的方法:handler是让 ...
随机推荐
- 关于linux系统CPU篇--->CPU使用率升高
1.CPU使用率为单位时间内CPU使用情况的统计,以百分比的方式展示. LINUX作为一个多任务操作系统,将每个CPU的时间划分为很短的时间片,再通过调度器轮流分配给各个任务使用,因此造成多任务同时运 ...
- 【vue】清理代码
// 一次性将这个日期选择器附加到一个输入框上 // 它会被挂载到 DOM 上. mounted: function () { // Pikaday 是一个第三方日期选择器的库 this.picker ...
- vue-cli3使用webpack-spritesmith配置雪碧图
一.背景问题 项目中如果有大量的小图标,如果不使用阿里的iconfont.UI给一个加一个,加一个引用一个,每个图标虽然很小,但是也是一次请求,每次请求都是消耗性能资源的. 二.解决思路 使用webp ...
- ASCII对应码表-键值(完整版)
ASCII对应码表-键值(完整版) Bin (二进制) Oct (八进制) Dec (十进制) Hex (十六进制) 缩写/字符 解释 0000 0000 00 0 0x00 NUL(null) 空字 ...
- C#调用VlcControl做一个播放器
开发环境: Visual Studio 2015 .Net Framework 4.5 1.新建一个Windows窗体应用程序 修改框架为.Net Framework 4.5 2.管理NuGet包 下 ...
- SQL Server2017还原数据库时指定mdf文件及日志文件的名称
由于需要还原同一个数据库的不同备份到不同数据库中,可是在还原的时候,可是在指定目标数据库时,填写不同的数据库名称,在SQL Server Data文件夹中生成的.mdf文件还是同一个,如图,虽然是很简 ...
- linux服务基础(三)之Httpd2.4配置
httpd-2.4 新特性: . MPM支持运行DSO机制,以模块形式按需加载 . 支持event MPM . 支持异步读写 . 支持每模块及每个目录分别使用各自的日志级别 . 每请求配置 <I ...
- 1、docker容器技术基础入门
Docker和传统虚拟机的区别 参考文章: https://lwn.net/Articles/531114/ 操作中的命名空间详解 https://blog.yadu ...
- 类中为什么要定义__init__()方法
总结一下, 加上__init__()方法后,类才可以实例化,不加类就是个空壳,相当于一个方法集合 学习Python的类,一直不太理解为什么一定要定义init()方法,现在简要谈一下自己的理解吧. 1. ...
- Python读写txt文件时的编码问题
这个问题来自于一个小伙伴,他在处理中文数据时需要先把里面的文本过滤然后分词,因为里面有许多符号,不仅是中文标点符号,还有✳,emoji等奇怪的符号. 正常情况下,中文的str经过encode('utf ...