当前位置:   article > 正文

python日志输出详细讲解版-logging库

python日志输出详细讲解版-logging库

一个成熟的软件产品,日志是必不可少的一部分,在python中我们怎么实现产品级别的日志输出呢?
python有一个内置模块logging,用来输出日志信息,可以进行各种配置,能满足我们大部分场景对日志的需求。

1、输出到控制台

导入logging模块,直接输出5个级别的日志信息,我们看一下会输出什么

  1. # -*- coding: utf-8 -*-
  2. import logging
  3. if __name__ == '__main__':
  4. logging.debug('debug级别,一般用来打印一些调试信息,级别最低')
  5. logging.info('info级别,一般用来打印一些正常的操作信息')
  6. logging.warning('waring级别,一般用来打印警告信息')
  7. logging.error('error级别,一般用来打印一些错误信息')
  8. logging.critical('critical级别,一般用来打印一些致命的错误信息,等级最高')

 1.1日志级别

会发现只输出下面三条信息,这是因为logging是分级别的,上面5个级别的信息从上到下依次递增,可以通过设置logging的level,使其只打印某个级别以上的信息。因为默认等级是 WARNING,所以只有 WARNING 以上级别的日志被打印出来。
如果我们想把debug和info也打印出来,可以使用 basicConfig 对其进行配置:

 基本上日志都是分级别的,这样可以让我们在不同的时期关注不同的重点,比如我们把一些调试的信息以debug的级别输出,并且把 logging 的 level 设为 DEBUG,这样我们以后不需要显示这些日志的时候,只需要把level设置为info或者更高即可

1.2输出格式

我们发现上面的日志输出信息很简略,暂时还不能满足我们的需求,比如我们可能需要输出该条信息的时间,所在位置等等,这同样可以通过basicConfig进行配置。

format 可以指定输出的内容和格式,其内置的参数如下:

  1. %(name)s:Logger的名字
  2. %(levelno)s:打印日志级别的数值
  3. %(levelname)s:打印日志级别的名称
  4. %(pathname)s:打印当前执行程序的路径,其实就是sys.argv[0]
  5. %(filename)s:打印当前执行程序名
  6. %(funcName)s:打印日志的当前函数
  7. %(lineno)d:打印日志的当前行号
  8. %(asctime)s:打印日志的时间
  9. %(thread)d:打印线程ID
  10. %(threadName)s:打印线程名称
  11. %(process)d:打印进程ID
  12. %(message)s:打印日志信息
  1. # -*- coding: utf-8 -*-
  2. import logging
  3. if __name__ == '__main__':
  4. logging.basicConfig(format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s',
  5. level=logging.DEBUG) # 配置输出格式、配置日志级别
  6. logging.debug('debug级别,一般用来打印一些调试信息,级别最低')
  7. logging.info('info级别,一般用来打印一些正常的操作信息')
  8. logging.warning('waring级别,一般用来打印警告信息')
  9. logging.error('error级别,一般用来打印一些错误信息')
  10. logging.critical('critical级别,一般用来打印一些致命的错误信息,等级最高')

 

2.输出日志到文件

以上我们只是把日志输出到控制台,但很多时候我们可能会需要把日志存到文件,这样程序出现问题时,可以方便我们根据日志信息进行定位。
最简单的方式是在basicConfig中配置filename和filemode

  1. # -*- coding: utf-8 -*-
  2. import logging
  3. if __name__ == '__main__':
  4. logging.basicConfig(format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s',
  5. level=logging.DEBUG,
  6. filename='demo.log',
  7. filemode='a') # 配置输出格式、日志级别、存储文件及文件打开模式
  8. logging.debug('debug级别,一般用来打印一些调试信息,级别最低')
  9. logging.info('info级别,一般用来打印一些正常的操作信息')
  10. logging.warning('waring级别,一般用来打印警告信息')
  11. logging.error('error级别,一般用来打印一些错误信息')
  12. logging.critical('critical级别,一般用来打印一些致命的错误信息,等级最高')

 这样就输出到文件中了

  

 其中参数 filemode表示文件打开模式,不设的话默认为’a’,即追加模式,可以不设;也可以设为’w’,每次写日志会覆盖之前的日志。
但是进行这样的操作之后,我们会发现控制台不输出了,怎么做到既输出到控制台又写入到文件呢?

2.1 logging 模块化设计


以上我们只是使用logging进行非常简单的操作,但这样作用有限,其实 logging 库采取了模块化的设计,提供了许多组件:记录器、处理器、过滤器和格式化器。

Logger 暴露了应用程序代码能直接使用的接口,用于记录日志。
Handler 将(记录器产生的)日志记录发送至合适的目的地(控制台、文件等)。
Filter 提供了更好的粒度控制,它可以决定输出哪些日志记录。
Formatter 指明了最终输出中日志记录的内容和格式。
简单地说,其中 Logger 是负责记录日志消息的,然后我们要把这些日志消息放到哪里,交给 Handler 处理,Filter 则帮我们过滤信息(不限于通过级别过滤),Formatter 就是跟上面的 format 一个意思,用来设置日志内容和格式。
这样,我们试一下使用模块的方式,重新记录日志
 

  1. # -*- coding: utf-8 -*-
  2. import logging
  3. if __name__ == '__main__':
  4. logger = logging.getLogger()
  5. logger.debug('debug级别,一般用来打印一些调试信息,级别最低')
  6. logger.info('info级别,一般用来打印一些正常的操作信息')
  7. logger.warning('waring级别,一般用来打印警告信息')
  8. logger.error('error级别,一般用来打印一些错误信息')
  9. logger.critical('critical级别,一般用来打印一些致命的错误信息,等级最高')

 

首先第一行 getLogger 获取了一个记录器,其中命名标识了这个 Logger。然后下面的输出方式跟我们一开始 logging 的用法是很相似的,看起来是不是很简单。我们没有配置handler,它默认输出到控制台。
那我们就给他加一个Handler吧,Handler的种类有很多,常用的有4种:

  1. logging.StreamHandler -> 控制台输出
  2. logging.FileHandler -> 文件输出
  3. logging.handlers.RotatingFileHandler -> 按照大小自动分割日志文件,一旦达到指定的大小重新生成文件
  4. logging.handlers.TimedRotatingFileHandler -> 按照时间自动分割日志文件

现在我们先使用最简单的StreamHandler把日志输出到控制台
 

  1. # -*- coding: utf-8 -*-
  2. import logging
  3. if __name__ == '__main__':
  4. logger = logging.getLogger('demo')
  5. stream_handler = logging.StreamHandler()
  6. logger.addHandler(stream_handler)
  7. logger.debug('debug级别,一般用来打印一些调试信息,级别最低')
  8. logger.info('info级别,一般用来打印一些正常的操作信息')
  9. logger.warning('waring级别,一般用来打印警告信息')
  10. logger.error('error级别,一般用来打印一些错误信息')
  11. logger.critical('critical级别,一般用来打印一些致命的错误信息,等级最高')

因为我们没有设置日志级别(第一层过滤,第二层过滤;第一层一般设为debug,第二层自定义)

使用Formatter模块设置一下输出格式

 同时将日志输出到控制台和文件(需要两个头)

  1. # -*- coding: utf-8 -*-
  2. import logging
  3. if __name__ == '__main__':
  4. logger = logging.getLogger('demo')
  5. logger.setLevel(level=logging.DEBUG)#相当于第一层过滤网
  6. formatter = logging.Formatter('%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
  7. #输出到文件
  8. file_handler = logging.FileHandler('demo2.log')#设置文件名,模式,编码
  9. file_handler.setLevel(level=logging.INFO)#相当于第二层过滤网;第一层之后的内容再次过滤。
  10. file_handler.setFormatter(formatter)
  11. # 输出到控制台
  12. stream_handler = logging.StreamHandler()
  13. stream_handler.setLevel(logging.DEBUG)#相当于第二层过滤网;第一层之后的内容再次过滤。
  14. stream_handler.setFormatter(formatter)
  15. logger.addHandler(file_handler)
  16. logger.addHandler(stream_handler)
  17. logger.debug('debug级别,一般用来打印一些调试信息,级别最低')
  18. logger.info('info级别,一般用来打印一些正常的操作信息')
  19. logger.warning('waring级别,一般用来打印警告信息')
  20. logger.error('error级别,一般用来打印一些错误信息')
  21. logger.critical('critical级别,一般用来打印一些致命的错误信息,等级最高')

 

 2.2 自动分割日志文件

  1. # -*- coding: utf-8 -*-
  2. import logging
  3. from logging import handlers
  4. if __name__ == '__main__':
  5. logger = logging.getLogger('demo')
  6. logger.setLevel(level=logging.DEBUG)
  7. formatter = logging.Formatter('%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
  8. file_handler = logging.FileHandler('demo2.log')
  9. file_handler.setLevel(level=logging.INFO)
  10. file_handler.setFormatter(formatter)
  11. stream_handler = logging.StreamHandler()
  12. stream_handler.setLevel(logging.DEBUG)
  13. stream_handler.setFormatter(formatter)
  14. # 实例化TimedRotatingFileHandler
  15. # interval是时间间隔
  16. # backupCount是备份文件的个数,如果超过这个个数,就会自动删除
  17. # when是间隔的时间单位,单位有以下几种:S 秒;M 分;H 小时;D 天;W 每星期(interval==0时代表星期一);midnight 每天凌晨
  18. time_rotating_handler = handlers.TimedRotatingFileHandler(
  19. filename='demo3.log',
  20. when='D',
  21. backupCount=10,
  22. encoding='utf-8') # 往文件里写入#指定间隔时间自动生成文件的处理器
  23. time_rotating_handler.setFormatter(formatter) # 设置文件里写入的格式
  24. logger.addHandler(file_handler)
  25. logger.addHandler(stream_handler)
  26. logger.addHandler(time_rotating_handler)
  27. logger.debug('debug级别,一般用来打印一些调试信息,级别最低')
  28. logger.info('info级别,一般用来打印一些正常的操作信息')
  29. logger.warning('waring级别,一般用来打印警告信息')
  30. logger.error('error级别,一般用来打印一些错误信息')
  31. logger.critical('critical级别,一般用来打印一些致命的错误信息,等级最高')

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/815926
推荐阅读
相关标签
  

闽ICP备14008679号