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 相关文章推荐
Python3实现将本地JSON大数据文件写入MySQL数据库的方法
Jun 13 Python
python实现Windows电脑定时关机
Jun 20 Python
Python OpenCV处理图像之图像直方图和反向投影
Jul 10 Python
Python实现购物评论文本情感分析操作【基于中文文本挖掘库snownlp】
Aug 07 Python
python-opencv颜色提取分割方法
Dec 08 Python
python实现共轭梯度法
Jul 03 Python
使用Python轻松完成垃圾分类(基于图像识别)
Jul 09 Python
Django项目基础配置和基本使用过程解析
Nov 25 Python
Python面向对象编程基础实例分析
Jan 17 Python
Django使用Celery加redis执行异步任务的实例内容
Feb 20 Python
python实现字符串和数字拼接
Mar 02 Python
Python实现将元组中的元素作为参数传入函数的操作
Jun 05 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
真正的ZIP文件操作类(php)
2007/07/21 PHP
浅谈thinkphp的实例化模型
2015/01/04 PHP
PHP实现操作redis的封装类完整实例
2015/11/14 PHP
PHP MYSQL实现登陆和模糊查询两大功能
2016/02/05 PHP
PHP递归遍历指定文件夹内的文件实现方法
2016/11/15 PHP
jquery下操作HTML控件的实现代码
2010/01/12 Javascript
转换json格式的日期为Javascript对象的函数
2010/07/13 Javascript
js获取元素在浏览器中的绝对位置
2010/07/24 Javascript
jQuery 自定义函数写法分享
2012/03/30 Javascript
node.js中的events.emitter.once方法使用说明
2014/12/10 Javascript
深入理解JavaScript系列(17):面向对象编程之概论详细介绍
2015/03/04 Javascript
js从外部获取图片的实现方法
2016/08/05 Javascript
实现easyui的datagrid导出为excel的示例代码
2016/11/10 Javascript
使用Vue动态生成form表单的实例代码
2018/04/26 Javascript
微信小程序云开发(数据库)详解
2019/05/17 Javascript
JavaScript Canvas编写炫彩的网页时钟
2019/10/16 Javascript
js实现漂亮的星空背景
2019/11/01 Javascript
Vue如何循环提取对象数组中的值
2020/11/18 Vue.js
使用typescript快速开发一个cli的实现示例
2020/12/09 Javascript
从零学Python之hello world
2014/05/21 Python
Python读取一个目录下所有目录和文件的方法
2016/07/15 Python
Python3匿名函数用法示例
2018/07/25 Python
python实现栅栏加解密 支持密钥加密
2019/03/20 Python
python数据类型之间怎么转换技巧分享
2019/08/20 Python
Python pip配置国内源的方法
2020/02/14 Python
html5 http的轮询和Websocket原理
2018/10/19 HTML / CSS
运动会广播稿400字
2014/01/25 职场文书
小学教师师德反思
2014/02/03 职场文书
xxx同志考察材料
2014/02/07 职场文书
制药工程专业职业生涯规划范文
2014/03/10 职场文书
销售员岗位职责
2014/06/09 职场文书
国庆节活动总结
2014/08/26 职场文书
银行自荐信怎么写
2015/03/05 职场文书
人事行政助理岗位职责
2015/04/11 职场文书
2015年库房管理工作总结
2015/10/14 职场文书
2016年植树节红领巾广播稿
2015/12/17 职场文书