python3中的logging记录日志实现过程及封装成类的操作


Posted in Python onMay 12, 2020

作用:

主要记录信息,便于定位查看问题。

python logging模块官网:

https://docs.python.org/zh-cn/3.7/library/logging.html#formatter-objects

三种定位问题方法:

print

debug调试:代码写好后,就不需要再进行调试了,所以引入了logger

logging.debug() ? 一般在测试环境中用

logger:当生产环境中有问题时,可以查看logger定位问题

步骤:

1.初始化日志 收集器

2.设置日志 收集器级别 -默认是warning

3.初始化日志 处理器 - 可以理解为写日志的笔

4.设置日志 处理器级别

5.添加handler

6.设置日志的格式

7.添加日志处理器

8.设置不同级别的logger

这里是引用

日志收集器级别

1.NOSET 0 等于没写,废话

2.DEBUG 10 程序调试bug时使用

3.INFO 20 程序正常运行时使用

4.WARNING 30 警告,程序未按预期运行时使用

5.ERROE 40 程序出错

6.CRITICAL 50 严重问题

如何定义级别:自己定的 可以结合try: except: 记录log

代码实现过程如下:

```python
import logging # 标准库,直接导入。
logger = logging.getLogger("日志名字") # 初始化日志收集器
logger.setLevel("DEBUG") # 设置日志收集器级别

handler = logging.FileHandler("日志路径") # 初始化日志处理器 - 文件输出(指定位置使用绝对路径,默认当前目录下)
handler.setLevel("warning") # 设置日志处理器级别 默认warning

console_handler = logging.StreamHandler() # 控制台输出
console_handler.setLevel("DEBUG")

logger.addHandler(handler) # 添加handler
logger.addHandler(console_handler)
 # 设置日志格式,中间间隔使用冒号也可以(模块名字-报错行-收集器名字-级别-信息)
fmt = logging.Formatter("%(filename)s-%(lineno)s-%(name)s-%(levelname)s-%(massage)s")
handler.setFormat(fmt) # 日志轮转 - 添加日志处理器
# 设置不同级别的logger -- 选择一个级别就可以
logging.info("")
logging.debug("")
logging.waring("")
logging.error("")
logging.critical("")

问题1:级别设置

如当设成debug的时候,只有高于,等于该级别的才会打印

如当你设成warning的时候,只有warning.error,critical才会打印

不用管(日志收集器)的级别是啥,这里设置就以(日志处理器)的级别

为准,两者中选择最高的如果(日志收集器)是warning,(日志处理器)

是debug,就以warning为准,两个都设置,这样可以添加多个handler

问题2:实例化

在模块中直接实例化,如果在外部实例化,容易造成多个日志文件的生成

问题3:日志格式设置,python logging官网,查找需要用到的。

https://docs.python.org/zh-cn/3.7/library/logging.html#formatter-objects

封装为类

import logging
class LoggerHandler(logging.Logger):

  def __init__(self,
         name="root",
         level="DEBUG",
         file=None,
         format="%(filename)s:%(lineno)d:%(name)s:%(levelname)s:%(message)s"
         ):

    # 初始化日志收集器
    logger = logging.getLogger(name)

    # 设置收集器级别
    logger.setLevel(level) # 继承了Logger 返回的实例就是自己

    # 初始化format,设置格式
    fmt = logging.Formatter(format)

    # 初始化处理器
    # 如果file为空,就执行stream_handler,如果有,两个都执行
    if file:
      file_handler = logging.FileHandler(file)
      # 设置handler级别
      file_handler.setLevel(level)
      # 添加handler
      logger.addHandler(file_handler)
      # 添加日志处理器
      file_handler.setFormatter(fmt)

    stream_handler = logging.StreamHandler()
    stream_handler.setLevel(level)
    logger.addHandler(stream_handler)
    stream_handler.setFormatter(fmt)

    self.logger = logger

	  def debug(self, msg):
	    return self.logger.debug(msg)
	  def info(self,msg):
	    return self.logger.info(msg)

	  def warning(self,msg):
	    return self.logger.warning(msg)
	 
	  def error(self,msg):
	    return self.logger.error(msg)
	 
	  def critical(self,msg):
	    return self.logger.critical(msg)
# 为了确保每次是同一个文件,调用同样的logger对象(防止手误写错文件名字),所以在这里直接初始化logger这个对象比较好
# 可以将name,file参数写入配置文件中(这里我是直接写到了配置文件当中,也可以直接传)
logger = LoggerHandler(config.logger_name,config.level,config.logger_file) 
# logger = LoggerHandler("python21",file="demo.txt")

if __name__ == '__main__':
  logger = LoggerHandler()
  logger.debug("world")
  # 测试.py:40:root:DEBUG:world - 应该是59行打印,因为信息早就保存到logger当中了 -- 可以直接继承logging.Logger使用

重新封装 - 继承logger后,发现可以直接定位到哪一行打印,可以查看源码

import logging

class LoggerHandler(logging.Logger):

  def __init__(self,
         name="root",
         level="DEBUG",
         file=None,
         format="%(filename)s:%(lineno)d:%(name)s:%(levelname)s:%(message)s"
         ):

    # logger(name) 直接超继承logger当中的name
    super().__init__(name) 

    # 设置收集器级别
    # logger.setLevel(level)
    self.setLevel(level) # 继承了Logger 返回的实例就是自己

    # 初始化format,设置格式
    fmt = logging.Formatter(format)

    # 初始化处理器
    # 如果file为空,就执行stream_handler,如果有,两个都执行
    if file:
      file_handler = logging.FileHandler(file)
      # 设置handler级别
      file_handler.setLevel(level)
      # 添加handler
      self.addHandler(file_handler)
      # 添加日志处理器
      file_handler.setFormatter(fmt)

    stream_handler = logging.StreamHandler()
    stream_handler.setLevel(level)
    self.addHandler(stream_handler)
    stream_handler.setFormatter(fmt) 
# 为了确保每次是同一个文件,调用同样的logger对象(防止手误写错文件名字),所以在这里直接初始化logger这个对象比较好
# 可以将name,file参数写入配置文件中(这里我是直接写到了配置文件当中,也可以直接传)
logger = LoggerHandler(config.logger_name,config.level,config.logger_file)
# logger = LoggerHandler("python21",file="demo.txt") 

if __name__ == '__main__':
  logger = LoggerHandler()
  logger.debug("world")
  # 继承后---测试.py:44:root:DEBUG:world

补充知识:python3使用logging包,把日志写到系统的rsyslog中

最近要写一个python程序写日志到rsyslog中,并通过配置rsyslog的文件来将他存到一个指定文件中。

首先,我想来看看logging提供的常用模块:

logger:logger主要是用来配置和发送日志消息的。可通过logging.getLogger(name)来返回一个logger对象。

不指定name就默认为root。

这里可以取一个合适的名字。

相同的name会返回同一个logger对象。在Formatter方法中用%(name)s在日志中打印出这个name。例如:

log = logging.getLogger('mylog')
log_format = logging.Formatter(
  'hhl-%(name)s-server[%(process)d]-%(levelname)s: %(message)s')
 
#打印结果示例:
#Aug 2 12:44:41 [localhost] hhl-mylog-server[7409]-DEBUG: debug message
handler:将日志记录发送到目的地,如文件,socket等。这里可以通过addHandler方法添加多个handler,可以实现日志的分级过滤。如果要把日志发送到rsyslog中,就可以采用SysLogHandler(),使用这个方法前需要导入他

from logging.handlers import SysLogHandler
这个方法有两个参数、一个是rsyslog中的facility:指定的是发送的设备,如kernel,mail,system等等,他还有local0-local7预留。这里我采用local5。还有一个参数指定的是log程序的地址,在centos7上默认是/dev/log。示例如下:

log_hdlr=SysLogHandler(facility=SysLogHandler.LOG_LOCAL5, address='/dev/log')
对应的rsyslog设置文件(/etc/rsyslog.conf):

local5.*   /var/log/all.log
#将local5的所有日志存入all.log文件中

如果想用handler对日志信息进行过滤,可以这样:

log_hdlr.setLevel(logging.ERROR)
#这里就指定了接收error以及更高级别的日志
 

formatter:指定日志的输出格式,包括消息格式和日期字符格式,例如:

log_format = logging.Formatter(
  'hhl-%(name)s-server[%(process)d]-%(levelname)s: %(message)s')
#输出示例
#Aug 2 12:44:41 [localhost] hhl-mylog-server[7409]-DEBUG: debug message

formatter可调用参数有:

%(name)s Logger的名字
%(levelname)s 文本形式的日志级别
%(message)s 用户输出的消息
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(levelno)s 数字形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有

由上面的这些模块就可以实现我想要的功能啦

将日志写入到all.log文件中-----源代码:

import logging
from logging.handlers import SysLogHandler
 
log = logging.getLogger('mylog')
log.setLevel(logging.DEBUG)
log_hdlr=SysLogHandler(facility=SysLogHandler.LOG_LOCAL5, address='/dev/log')
log_format = logging.Formatter(
  'hhl-%(name)s-server[%(process)d]-%(levelname)s: %(message)s')
log_hdlr.setFormatter(log_format)
log_hdlr.setLevel(logging.ERROR)#接受error及以上的日志信息
log.addHandler(log_hdlr)
log.debug('debug message test')#指明级别为debug
log.error('error message test')#指明级别为error
#最后只保存error及更高优先级的日志

可能有些地方说的不对,还望大家能够指正!

以上这篇python3中的logging记录日志实现过程及封装成类的操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
自己使用总结Python程序代码片段
Jun 02 Python
Python按行读取文件的简单实现方法
Jun 22 Python
Python实现计算两个时间之间相差天数的方法
May 10 Python
分享一下如何编写高效且优雅的 Python 代码
Sep 07 Python
Python使用re模块正则提取字符串中括号内的内容示例
Jun 01 Python
Python 剪绳子的多种思路实现(动态规划和贪心)
Feb 24 Python
Python基于paramunittest模块实现excl参数化
Apr 26 Python
python logging.info在终端没输出的解决
May 12 Python
python字典key不能是可以是啥类型
Aug 04 Python
Python切片列表字符串如何实现切换
Aug 06 Python
只用20行Python代码实现屏幕录制功能
Jun 02 Python
Python超详细分步解析随机漫步
Mar 17 Python
Pycharm激活方法及详细教程(详细且实用)
May 12 #Python
PyTorch在Windows环境搭建的方法步骤
May 12 #Python
pycharm 2018 激活码及破解补丁激活方式
Sep 21 #Python
pycharm 激活码及使用方式的详细教程
May 12 #Python
Python-jenkins模块之folder相关操作介绍
May 12 #Python
使用python-Jenkins批量创建及修改jobs操作
May 12 #Python
Python如何使用队列方式实现多线程爬虫
May 12 #Python
You might like
PHP memcache扩展的三种安装方法
2009/04/26 PHP
php查询相似度最高的字符串的方法
2015/03/12 PHP
PHP使用正则表达式获取微博中的话题和对象名
2015/07/18 PHP
PHP生成可点击刷新的验证码简单示例
2016/05/13 PHP
学习ExtJS Column布局
2009/10/08 Javascript
jQuery Ajax之$.get()方法和$.post()方法
2009/10/12 Javascript
jQuery)扩展jQuery系列之一 模拟alert,confirm(一)
2010/12/04 Javascript
js替换字符串的所有示例代码
2013/07/23 Javascript
浅析offsetLeft,Left,clientLeft之间的区别
2013/11/30 Javascript
jquery操作checked属性以及disabled属性的多种方法
2014/06/20 Javascript
IE6/IE7中JavaScript json提示缺少标识符、字符串或数字问题处理
2014/12/16 Javascript
jQuery制作效果超棒的手风琴折叠菜单
2015/04/03 Javascript
jquery 中toggle的2种用法详解(推荐)
2016/09/02 Javascript
jQuery+CSS3实现四种应用广泛的导航条制作实例详解
2016/09/17 Javascript
JS常见算法详解
2017/02/28 Javascript
jQuery EasyUI 为Combo,Combobox添加清除值功能的实例
2017/04/13 jQuery
angular.js4使用 RxJS 处理多个 Http 请求
2017/09/23 Javascript
vue+axios 前端实现的常用拦截的代码示例
2018/08/23 Javascript
JavaScript显式数据类型转换详解
2019/03/18 Javascript
layui实现把数据表格时间戳转换为时间格式的例子
2019/09/12 Javascript
基于redis的小程序登录实现方法流程分析
2020/05/25 Javascript
[02:36]DOTA2上海特锦赛 回忆电竞生涯的重要瞬间
2016/03/25 DOTA
python获取当前日期和时间的方法
2015/04/30 Python
python脚本替换指定行实现步骤
2017/07/11 Python
python技能之数据导出excel的实例代码
2017/08/11 Python
Python闭包执行时值的传递方式实例分析
2018/06/04 Python
python dataframe 输出结果整行显示的方法
2018/06/14 Python
Python实现ATM系统
2020/02/17 Python
Django Model中字段(field)的各种选项说明
2020/05/19 Python
关于python中remove的一些坑小结
2021/01/04 Python
企业安全生产演讲稿
2014/05/09 职场文书
三分钟自我介绍演讲稿
2014/08/21 职场文书
导航工程专业自荐信
2014/09/02 职场文书
2016会计专业自荐信范文
2016/01/28 职场文书
《哪吒之魔童降世》观后感:世上哪有随随便便的成功
2019/11/08 职场文书
Python办公自动化之Excel(中)
2021/05/24 Python