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中dictionary items()系列函数的用法实例
Aug 21 Python
Python中的闭包总结
Sep 18 Python
Python实现可设置持续运行时间、线程数及时间间隔的多线程异步post请求功能
Jan 11 Python
python 中的list和array的不同之处及转换问题
Mar 13 Python
python读取文件名称生成list的方法
Apr 27 Python
Python下调用Linux的Shell命令的方法
Jun 12 Python
Python实现Linux监控的方法
May 16 Python
Python上下文管理器类和上下文管理器装饰器contextmanager用法实例分析
Nov 07 Python
在django-xadmin中APScheduler的启动初始化实例
Nov 15 Python
python 追踪except信息方式
Apr 25 Python
Python无损压缩图片的示例代码
Aug 06 Python
关于python类SortedList详解
Sep 04 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中关于长度计算容易混淆的问题分析
2016/05/27 PHP
PHP中overload与override的区别
2017/02/13 PHP
CodeIgniter整合Smarty的方法详解
2017/08/25 PHP
laravel框架数据库配置及操作数据库示例
2019/10/10 PHP
一个用js实现的页内搜索代码
2007/05/23 Javascript
实现png图片和png背景透明(支持多浏览器)的方法
2009/09/08 Javascript
jquery 插件实现图片延迟加载效果代码
2010/02/06 Javascript
javascript学习笔记(十六) 系统对话框(alert、confirm、prompt)
2012/06/20 Javascript
用unescape反编码得出汉字示例
2014/04/24 Javascript
Javascript 完美运动框架(逐行分析代码,让你轻松了运动的原理)
2015/01/23 Javascript
javascript使用Promise对象实现异步编程
2016/03/01 Javascript
浅谈JavaScript for循环 闭包
2016/06/22 Javascript
JS基于onclick事件实现单个按钮的编辑与保存功能示例
2017/02/13 Javascript
详解Angularjs 自定义指令中的数据绑定
2018/07/19 Javascript
JavaScript数据结构与算法之二叉树插入节点、生成二叉树示例
2019/02/21 Javascript
vue+webpack 更换主题N种方案优劣分析
2019/10/28 Javascript
Python代理抓取并验证使用多线程实现
2013/05/03 Python
Python中的迭代器与生成器高级用法解析
2016/06/28 Python
python版大富翁源代码分享
2018/11/19 Python
Python Pexpect库的简单使用方法
2019/01/29 Python
Python爬虫HTPP请求方法有哪些
2020/06/03 Python
使用Python pip怎么升级pip
2020/08/11 Python
opencv python 对指针仪表读数识别的两种方式
2021/01/14 Python
如何使用localstorage代替cookie实现跨域共享数据问题
2018/04/18 HTML / CSS
加拿大著名时装品牌:SOIA & KYO
2016/08/23 全球购物
一套带答案的C++笔试题
2014/01/10 面试题
自荐书封面下载
2013/11/29 职场文书
高中生学习的自我评价
2013/12/14 职场文书
歌颂祖国的演讲稿
2014/05/04 职场文书
巾帼建功标兵事迹材料
2014/05/11 职场文书
教师三严三实对照检查材料
2014/09/25 职场文书
2014年光棍节活动策划方案(创意集锦)
2014/09/29 职场文书
健康状况证明模板
2014/10/23 职场文书
校本培训个人总结
2015/02/28 职场文书
公司总经理岗位职责
2015/04/01 职场文书
python 判断文件或文件夹是否存在
2022/03/18 Python