所有 Python 程序员必须要学会的「日志」记录。
本文字数:3840 字
阅读本文大概需要:10 分钟
写在之前
在我们的现实生活中,「日志记录」其实是一件非常重要的事情,比如银行的转账记录,汽车的行车记录仪记录行驶过程中的一切,如果出现了什么问题,我们可以通过「日志记录」来搞清楚到底发生了什么事情。
除了在生活中,在日常的系统开发以及调试等过程中,记录日志同样是一件很重要的事情。很多编程初学者并没有「记录日志」的习惯,认为记录日志是一件可有可无的事情,出现问题的时候只要使用 print 函数打印一下程序的中间结果即可,真是 too young too naive。只是 print 的话对于简单的脚本程序来说或许可行,可是到了碰到复杂的系统,你如果还是只用 print 这种方式的话,你会看到大量的消息,看到吐也不一定能找到其中有用的消息。
「日志」是一个系统的重要组成部分,用来记录用户操作、系统运行状态和错误信息,它的好坏直接影响到系统出现问题时定位的速度,有日志记录,我们可以在服务崩溃的时候很快的通过查看日志来发现问题出现的地方,同样也可以通过对日志的观察和分析,提前发现系统可能存在的风险。
Python 的标准日志模块
上面我们说了「日志」是如此的重要,作为无所不能的 Python 当然也有日志相关的功能,Python 标准库中提供了 logging 模块供我们使用。在最简单的使用中,默认情况下 logging 将日志打印到屏幕终端,我们可以直接导入 logging 模块,然后调用 debug,info,warn,error 和 critical 等函数来记录日志,默认日志的级别为 warning,级别比 warning 高的日志才会被显示(critical > error > warning > info > debug),「级别」是一个逻辑上的概念,用来区分日志的重要程度。
import logging
logging.debug('debug message')
logging.info("info message")
logging.warn('warn message')
logging.error("error message")
logging.critical('critical message')
上述代码的执行结果如下所示:
WARNING:root:warn message
ERROR:root:error message
CRITICAL:root:critical message
我在上面说过,用 print 的话会产生大量的信息,从而很难从中找到真正有用的信息。而 logging 中将日志分成不同的级别以后,我们在大多数时间只保存级别比较高的日志信息,从而提高了日志的性能和分析速度,这样我们就可以很快速的从一个很大的日志文件里找到错误的信息。
配置日志格式
我们在用 logging 来记录日志之前,先来进行一些简单的配置:
import logging
logging.basicConfig(filename= 'test.log', level= logging.INFO)
logging.debug('debug message')
logging.info("info message")
logging.warn('warn message')
logging.error("error message")
logging.critical('critical message')
运行上面的代码以后,会在当前的目录下新建一个 test.log 的文件,这个文件中存储 info 以及 info 以上级别的日志记录。运行一次的结果如下所示:
INFO:root:info message
WARNING:root:warn message
ERROR:root:error message
CRITICAL:root:critical message
上面的例子中,我是用 basicConfig 对日志进行了简单的配置,其实我们还可以进行更为复杂些的配置,在此之前,我们先来了解一下 logging 中的几个概念:
- Logger:日志记录器,是应用程序中可以直接使用的接口。
- Handler:日志处理器,用以表明将日志保存到什么地方以及保存多久。
- Formatter:格式化,用以配置日志的输出格式。
上述三者的关系是:一个 Logger 使用一个 Handler,一个 Handler 使用一个 Formatter。那么概念我们知道了,该如何去使用它们呢?我们的 logging 中有很多种方式来配置文件,简单的就用上面所说的 basicConfig,对于比较复杂的我们可以将日志的配置保存在一个配置文件中,然后在主程序中使用 fileConfig 读取配置文件。
基本的知识我们知道了,下面我们来做一个小的题目:日志文件保存所有 debug 及其以上级别的日志,每条日志中要有打印日志的时间,日志的级别和日志的内容。请先自己尝试着思考一下,如果你已经思考完毕请继续向下看:
import logging
logging.basicConfig(
level= logging.DEBUG,
format = '%(asctime)s : %(levelname)s : %(message)s',
filename= "test.log"
)
logging.debug('debug message')
logging.info("info message")
logging.warn('warn message')
logging.error("error message")
logging.critical('critical message')
上述代码的一次运行结果如下:
2018-10-19 22:50:35,225 : DEBUG : debug message
2018-10-19 22:50:35,225 : INFO : info message
2018-10-19 22:50:35,225 : WARNING : warn message
2018-10-19 22:50:35,225 : ERROR : error message
2018-10-19 22:50:35,225 : CRITICAL : critical message
我刚刚在上面说过,对于比较复杂的我们可以将日志的配置保存在一个配置文件中,然后在主程序中使用 fileConfig 读取配置文件。下面我们就来看一个典型的日志配置文件(配置文件名为 logging.conf):
[loggers]
keys = root
[handlers]
keys = logfile
[formatters]
keys = generic
[logger_root]
handlers = logfile
[handler_logfile]
class = handlers.TimedRotatingFileHandler
args = ('test.log', 'midnight', 1, 10)
level = DEBUG
formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s] %(message)s
在上述的日志配置文件中,首先我们在 [loggers] 中声明了一个叫做 root 的日志记录器(logger),在 [handlers] 中声明了一个叫 logfile 的日志处理器(handler),在 [formatters] 中声明了一个名为 generic 的格式化(formatter)。之后在 [logger_root] 中定义 root 这个日志处理器(logger) 所使用的日志处理器(handler) 是哪个,在 [handler_logfile] 中定义了日志处理器(handler) 输出日志的方式、日志文件的切换时间等。最后在 [formatter_generic] 中定义了日志的格式,包括日志的产生时间,级别、文件名以及行号等信息。
有了上述的配置文件以后,我们就可以在主代码中使用 logging.conf 模块的 fileConfig 函数加载日志配置:
import logging
import logging.config
logging.config.fileConfig('logging.conf')
logging.debug('debug message')
logging.info("info message")
logging.warn('warn message')
logging.error("error message")
logging.critical('critical message')
上述代码的运行一次的结果如下所示:
2018-10-19 23:00:02,809 WARNI [root:8] warn message
2018-10-19 23:00:02,809 ERROR [root:9] error message
2018-10-19 23:00:02,809 CRITI [root:10] critical message
写在之后
正如标题中所说的那样,我认为「日志记录」是每个 Python 程序员必须要知道且学会的东西,也是每个程序员必须具备的意识。如果你之前没有使用过日志亦或者说不知道该怎么去使用日志记录,这篇文章我相信会给你带来一些帮助。
Python 的日志库设计之好,用起来之灵活,可以说是 Python 标准库中相当优秀的存在。当然上面我们所说的只是 Python 日志库中很少的一部分,更多的操作和内容还需要你在今后的学习和实践中自己去发掘和运用。
更多内容,欢迎关注公众号「Python空间」,期待和你的交流。
所有 Python 程序员必须要学会的「日志」记录。的更多相关文章
- Java程序员都需要懂的「反射」
前言 只有光头才能变强. 文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y 今天来简单写一下Java的反射.本来没打算写反射 ...
- 月薪3万的python程序员都看了这本书
想必大家都看过吧 Python编程从入门到实践 全书共有20章,书中的简介如下: 本书旨在让你尽快学会 Python ,以便能够编写能正确运行的程序 —— 游戏.数据可视化和 Web 应用程序,同时掌 ...
- 国外一教授坦言,用这方法能迅速成为python程序员,但都不愿意说_编程小十
越来越多的人学习python,但你学习python用了多长的时间?#Python# 你知道如何才能迅速掌握并成为python程序员吗? 有这样的一位国外的教授说,要迅速成为python程序员,几乎 ...
- 成为python程序员,对疫情过后的毕业生来说,真是一个不错的方向吗?
Python最近几年,一直被炒得很火,这其中有商业因素,但更重要的是即将到来的人工智能时代,而python就恰好是最适合的编程语言. 所以无论是在职的人,还是在校的学生,都想着跟上这一趋势,但,在今年 ...
- 技术|程序员必须要学会Google搜索技巧
程序员必须要学会Google搜索技巧 摘要: 因为Google在我天朝被墙,学FQ请通过Bing进行搜索如何FQGoogle搜索技巧我曾经多次劝我的另一个朋友花10分钟学习一下Google通配符的使用 ...
- Python程序员的进化史
各种程序员所写的阶乘算法代码 # -*- coding: utf-8 -*- #新手程序员(递归) def factorial(x): if x == 0: return 1 else: return ...
- 介绍Python程序员常用的IDE和其它开发工具
概述 “工欲善其事,必先利其器”,如果说编程是程序员的手艺,那么IDE就是程序员的吃饭家伙了. IDE 的全称是Integration Development Environment(集成开发环境), ...
- Python程序员去上海工作有多难?
我只能说,也要看你掌握的技术可以打多少分.技术熟练度跟找工作的难易程度是成正比的:你掌握得越好,找工作就越容易(难度系数越低):反之越高. Python程序员这种技术类的工作岗位,当然还是要有扎实的技 ...
- 做为一个Python程序员的基本素养
今天在学习的过程中,明白了一些不是Python标准所必须要做的事情,二是做为一个合格的Python程序员应该所遵从的一些规范 分享给大家,有不足的地方请大家指正,此下是我学习的一点心得: 1.在给变量 ...
随机推荐
- 二、C++复数的实现
C++复数的实现 在数字图像处理领域,复数这一类型会被经常使用到.但是在C++和Qt中都没有可以使用的复数类.为了今后的方便,我们可以自己定义一个C++复数类,以便将来使用. 一.复数的属性 复数包含 ...
- [转]超全!iOS 面试题汇总
转自:http://www.cocoachina.com/programmer/20151019/13746.html 1. Object-c的类可以多重继承么?可以实现多个接口么?Category是 ...
- pta 编程题6 树的同构
其它pta数据结构编程题请参见:pta 题目请参见:树的同构 因题目中左右子树是按照下标给出,因此用数组存放树是更好的方法. 判断两棵树是否同构:用递归的方法.如果当前两个结点都为空,则返回TRUE: ...
- 论overflow滚动的重要性
原理 设置一个块级作用域溢出的效果,只需要在外部块的位置上设置overflow:scroll和height:xx即可. 此时,块级作用域的内容位移超出外部块的位移就会出现滚动条,当内部块滚动时,我们能 ...
- TFS看板的迭代规划
故事点 故事点更多体现的是用户情景或者bug的规模,采用斐波拉契数列(1,2,3,5,8,13)这样的数字表示,包含如下内容: 相对工作量 复杂度 风险和不确定性 相对工作量 下面演示一个Case来说 ...
- 2018.2.6 JS-判断用户浏览器
JS-判断用户浏览器 在判断用户使用的浏览器是否为PC还是移动设备,有时候项目中需要用到.可在需要的项目中当全局方法来使用. 判断代码 function getMoblieDevice(window) ...
- python实现二叉树的镜像
题目描述 操作给定的二叉树,将其变换为源二叉树的镜像. 输入描述: 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / \ 10 6 / \ / \ ...
- ARC机制中的Strong和weak
什么是ARC Automatic Reference Counting,自动引用计数,即ARC,可以说是WWDC2011和iOS5所引入的最大的变革和最激动人心的变化.ARC是新的LLVM 3.0编译 ...
- 井字游戏 人机对战 java实现
package com.ecnu.Main; /** * 主函数触发游戏 */public class MainApplication { public static void main(String ...
- Uva 填充正方形
暴力出奇迹 #include<iostream> #include<cstdio> using namespace std; +; int T,n; char S[maxn][ ...