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 相关文章推荐
Python操作sqlite3快速、安全插入数据(防注入)的实例
Apr 26 Python
web.py在SAE中的Session问题解决方法(使用mysql存储)
Jun 24 Python
使用Python实现BT种子和磁力链接的相互转换
Nov 09 Python
Python黑帽编程 3.4 跨越VLAN详解
Sep 28 Python
Python 模拟员工信息数据库操作的实例
Oct 23 Python
python+Splinter实现12306抢票功能
Sep 25 Python
pandas pivot_table() 按日期分多列数据的方法
Nov 16 Python
python读文件的步骤
Oct 08 Python
Python3 assert断言实现原理解析
Mar 02 Python
Python基于pip实现离线打包过程详解
May 15 Python
Python实现一个简单的递归下降分析器
Aug 01 Python
python实现简单遗传算法
Sep 18 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/07/01 PHP
php设计模式之组合模式实例详解【星际争霸游戏案例】
2020/03/27 PHP
javascript vvorld 在线加密破解方法
2008/11/13 Javascript
ExtJS 2.0实用简明教程之应用ExtJS
2009/04/29 Javascript
兼容IE与firefox火狐的回车事件(js与jquery)
2010/10/20 Javascript
jquerymobile局部渲染的各种刷新方法小结
2014/03/05 Javascript
使用typeof判断function是否存在于上下文
2014/08/14 Javascript
Node.js 的异步 IO 性能探讨
2014/10/08 Javascript
javascript删除一个html元素节点的方法
2014/12/20 Javascript
javascript封装的sqlite操作类实例
2015/07/17 Javascript
学习JavaScript设计模式(链式调用)
2015/11/26 Javascript
jquery实现删除一个元素后面的所有元素功能
2015/12/21 Javascript
javascript每日必学之循环
2016/02/19 Javascript
原生js三级联动的简单实现代码
2016/06/07 Javascript
JavaScript SHA-256加密算法详细代码
2016/10/06 Javascript
微信小程序 图片等比例缩放(图片自适应屏幕)
2016/11/16 Javascript
详解vuelidate 对于vueJs2.0的验证解决方案
2017/03/09 Javascript
vue获取时间戳转换为日期格式代码实例
2019/04/17 Javascript
利用原生JavaScript实现造日历轮子实例代码
2019/05/08 Javascript
基于vue实现一个禅道主页拖拽效果
2019/05/27 Javascript
vue el-tree 默认展开第一个节点的实现代码
2020/05/15 Javascript
[02:27]2018DOTA2亚洲邀请赛趣味视频之钓鱼大赛 谁是垂钓冠军?
2018/04/05 DOTA
Django开发的简易留言板案例详解
2018/12/04 Python
python gdal安装与简单使用
2019/08/01 Python
PyCharm无法识别PyQt5的2种解决方法,ModuleNotFoundError: No module named 'pyqt5'
2020/02/17 Python
Python并发爬虫常用实现方法解析
2020/11/19 Python
利用HTML5中Geolocation获取地理位置调用Google Map API在Google Map上定位
2013/01/23 HTML / CSS
英国排名第一的礼品体验公司:Red Letter Days
2018/08/16 全球购物
Hawes & Curtis澳大利亚官网:英国经典服饰品牌
2018/10/29 全球购物
New Balance加拿大官方网站:运动鞋和健身服装
2018/11/19 全球购物
高三自我评价
2014/02/01 职场文书
数控技校生自我鉴定
2014/03/02 职场文书
妇女工作先进事迹
2014/08/17 职场文书
警察正风肃纪剖析材料
2014/10/16 职场文书
2015年行政执法工作总结
2015/05/23 职场文书
红色经典观后感
2015/06/18 职场文书