Python Logging 日志记录入门学习


Posted in Python onJune 02, 2018

Python Logging原来真的远比我想象的要复杂很多很多,学习路线堪比git。但是又绕不过去,alternatives又少,所以必须要予以重视,踏踏实实认认真真的来好好学学才行。

学习Logging的目的:

简单脚本还好,print足够。

但是稍微复杂点,哪怕是三四个文件加起来两三百行代码,调试也开始变复杂起来了。

再加上如果是后台长期运行的那种脚本,运行信息的调查更是复杂起来。

一开始我还在各种查crontab的日志查看,或者是python后台运行查看,或者是python stdout的获取等等,全都找错了方向。

真正的解决方案在于正确的logging。

记录好了的话,我不需要去找python的控制台输出stdout,也不需要找crontab的日志,只需要查看log文件即可。

下面是python的logging学习记录。

最简单的日志输出(无文件记录)

import logging
 
logging.error("出现了错误")
logging.info("打印信息")
logging.warning("警告信息")

首先,忘掉logging.info()! 忘掉logging.basicConfig()!

网上各种关于python logging的文章实在是太不体谅新手了,logging这么复杂的东西竟然想表现得很简单,还用各种简单的东西做假象。

实际上我们真正要用起来的日志,绝对是不会直接用logging.info()logging.basicConfig()这样的,这是此模块的官方推出来迷惑人的——看似让你一键上手,快速看到结果,但是跟实际真的不搭!

所以为了后面解释起来轻松,必须先警告这点:忘记它们俩!

记住,唯一要用到logging.什么的,就只有logging.getLogger()这一次。

了解logging的工作流

不想上流程图一类的东西,那样反而更迷糊。

简单说吧:

logging模块是会自动将你自定制的logger对象全局化的,

也就是说,你在自己的模块里只要定义了一次某个logger,比如叫log,那么只要是在同一个模块中运行的其他文件都能读取到它。

比如说,你在主文件main.py中自定义了一个logger,可能设置了什么输出文件、输出格式什么的,然后你在main.py中会引用一些别的文件或模块,比如sub.py,那么在这个sub.py中你什么都不用设置,只要用一句logger = logging.getLogger('之前在main.py定义的日志名')即可获得之前的一切自定义设置。

当然,被调用的文件(先称为子模块)中,用logging.getLogger('日志名')时,最好在日志名后加一个.子名称这样的,比如main.sub。这样输出的时候就会显示出来某条日志记录是来自于这个文件里了。当然,.前面的父级logger必须名字一致,是会被识别出来的!

然后,子日志还可以再子日志,甚至一个子模块可以再让所有函数各又一个子子日志,比如main.sub.func1这样的。logging都会根据.识别出来上下级关系的。

这样一说,实际上也就是class类继承的那种机制了。你按照父级名称继承,然后还可以改写自己的新设置等。

了解了这些概念以后,才能来谈代码。实际上也就好理解多了。

设置logger的方法

看来看去,这篇文章说得比较全面也最清楚,以下很多都参考到它的内容:Python 101: An Intro to logging

一般想要自定义一个logger,比如让它输出信息时按照什么格式显示,输出到哪个文件,要不要输出到屏幕一类,有三种方法可以达到设置:

  1. 直接在python代码里设置
  2. 用外部的config.ini文件配置
  3. 用python的dict字典配置

三种达到的目的都是一样的,字典用的人很少也不方便,配置文件比较好用只是.ini的语法不是很方便读,且不容易做到变量的动态设置,所以一般直接在python代码里写就好。

常用设置语句

以下是程序主入口文件的通用写法,注意,一定要在主入口定义好logger,这样其他所有的子模块才能够继承到。

#  main.py
import logging
import otherMod2  # 等下会调用到的子模块

def main():
  """
  这个文件是程序的主入口
  """

  define_logger()

  log = logging.getLogger('exampleApp')

  # 输出信息测试
  logger.info("Program started")
  result = otherMod2.add(7, 8)   # 这个是来自别的模块的方法
  logger.info("Done!")

def define_logger():
  logger = logging.getLogger("exampleApp")
  logger.setLevel(logging.INFO)

  # 设置输出格式
  formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
 
  # 设置日志文件处理器
  fh = logging.FileHandler("new_snake.log")
  fh.setFormatter(formatter)  # 为这个处理器添加格式

  # 设置屏幕stdout输出处理器
  sh = logging.StreamHandler(stream=None)
  sh.setFormatter(formatter)
 
  # 把处理器加到logger上
  logger.addHandler(fh)
  logger.addHandler(sh)
 
if __name__ == "__main__":
  main()

下面是子模块中的调用方法(很简单):

# otherMod2.py
import logging
 
module_logger = logging.getLogger("exampleApp.otherMod2")

def add(x, y):
  # 这里一句`getLogger`就继承到父级的logger了
  logger = logging.getLogger("exampleApp.otherMod2.add")

  # 输出测试
  logger.info("added %s and %s to get %s" % (x, y, x+y))
  return x+y

注意,主文件中,在什么地方定义logger都可以,可以在main()里也可以在任何单独的函数或类里,无所谓。只要在调用子模块之前定义好了就可以了。一旦定义过,日志名就会被记下来,然后子模块就可以轻松继承到。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python3访问sina首页中文的处理方法
Feb 24 Python
python删除列表内容
Aug 04 Python
Python中取整的几种方法小结
Jan 06 Python
使用python爬取B站千万级数据
Jun 08 Python
Python BS4库的安装与使用详解
Aug 08 Python
python爬取酷狗音乐排行榜
Feb 20 Python
利用python计算时间差(返回天数)
Sep 07 Python
Python 可变类型和不可变类型及引用过程解析
Sep 27 Python
Django实现文件上传和下载功能
Oct 06 Python
Python selenium使用autoIT上传附件过程详解
May 26 Python
python实现大文本文件分割成多个小文件
Apr 20 Python
Python自动化实战之接口请求的实现
May 30 Python
python实现寻找最长回文子序列的方法
Jun 02 #Python
python实现对求解最长回文子串的动态规划算法
Jun 02 #Python
Python 网络爬虫--关于简单的模拟登录实例讲解
Jun 01 #Python
用Python一键搭建Http服务器的方法
Jun 01 #Python
python 编写简单网页服务器的实例
Jun 01 #Python
Django中间件实现拦截器的方法
Jun 01 #Python
Python使用add_subplot与subplot画子图操作示例
Jun 01 #Python
You might like
php类常量的使用详解
2013/06/08 PHP
解析PHP中的unset究竟会不会释放内存
2013/07/18 PHP
PHP中功能强大却很少使用的函数实例小结
2016/11/10 PHP
详解yii2实现分库分表的方案与思路
2017/02/03 PHP
php+js实现的无刷新下载文件功能示例
2019/08/23 PHP
PHP文件打开关闭及读写操作示例解析
2020/08/06 PHP
PHP终止脚本运行三种实现方法详解
2020/09/01 PHP
JavaScript 函数replace深入了解
2013/03/14 Javascript
简单几行JS Code实现IE邮件转发新浪微博
2013/07/03 Javascript
$.each遍历对象、数组的属性值并进行处理
2014/07/18 Javascript
关于JS中match() 和 exec() 返回值和属性的测试
2016/03/21 Javascript
JavaScript 对象字面量讲解
2016/06/06 Javascript
JSP基于Bootstrap分页显示实例解析
2016/06/12 Javascript
JS基于构造函数实现的菜单滑动显隐效果【测试可用】
2016/06/21 Javascript
jQuery实现打开页面渐现效果示例
2016/07/27 Javascript
JavaScript性能优化总结之加载与执行
2016/08/11 Javascript
Angular中使用MathJax遇到的一些问题
2017/12/15 Javascript
微信小程序与webview交互实现支付功能
2019/06/07 Javascript
微信小程序组件传值图示过程详解
2019/07/31 Javascript
使用vue打包进行云服务器上传的问题
2020/03/02 Javascript
[32:47]完美世界DOTA2联赛 GXR vs IO 第二场 11.07
2020/11/09 DOTA
tensorflow使用神经网络实现mnist分类
2018/09/08 Python
Python 创建新文件时避免覆盖已有的同名文件的解决方法
2018/11/16 Python
Python设计模式之策略模式实例详解
2019/01/21 Python
在python中实现调用可执行文件.exe的3种方法
2019/07/07 Python
python mysql中in参数化说明
2020/06/05 Python
用Python爬取LOL所有的英雄信息以及英雄皮肤的示例代码
2020/07/13 Python
详解css3中的伪类before和after常见用法
2020/11/17 HTML / CSS
详解移动端h5页面根据屏幕适配的四种方案
2020/04/15 HTML / CSS
char型变量中能不能存贮一个中文汉字
2015/07/08 面试题
财务总监岗位职责
2014/03/07 职场文书
监察建议书范文
2014/03/12 职场文书
英语教师求职信范文
2015/03/20 职场文书
nginx前后端同域名配置的方法实现
2021/03/31 Servers
MySQL高速缓存启动方法及参数详解(query_cache_size)
2021/07/01 MySQL
利用Python读取微信朋友圈的多种方法总结
2021/08/23 Python