Python logging 记录日志

目录

1.使用Python的 logging 模块记录日志

2. Python log 的日志级别

3.logging 日志格式

4.logging 模块:Logger 、Handler、Filter、Formatter

5.自动分割日志文件-日志文件按照时间划分或者按照大小划分

6总结与扩展

7 Linux 下的 rsyslog 日志服务器

8.参考


官方文档:

[1]https://docs.python.org/2/library/logging.html

0.程序日志的重要性

程序日志的重要性不言而喻,定位问题就会用到日志信息;另外,通过跟踪日志,也可以快速了解他人写的代码的执行情况。

1.使用Python的 logging 模块记录日志

下面给出一个例子,使用 logging 模块以一定的格式向控制台和本地日志文件  输出 程序执行过程中的日志信息:

#-*- coding: UTF-8 -*- 
#!/usr/bin/env python

import logging

def MyLogTest():
    logger = logging.getLogger('MyLogTest')
    logger.setLevel(level=logging.INFO)
    
    LogFormat=logging.Formatter('%(asctime)s - %(pathname)s - %(filename)s-%(funcName)s-[line:%(lineno)d] - %(levelname)s: %(message)s')
    
    file_handler = logging.FileHandler('MyLogTest.log')
    file_handler.setLevel(level=logging.INFO)
    file_handler.setFormatter(LogFormat)
      
    stream_handler = logging.StreamHandler()
    stream_handler.setLevel(logging.DEBUG)
    stream_handler.setFormatter(LogFormat)
    
    logger.addHandler(file_handler)
    logger.addHandler(stream_handler)
      
    logger.debug('debug级别,一般用来打印一些调试信息,级别最低')
    logger.info('info级别,一般用来打印一些正常的操作信息')
    logger.warning('waring级别,一般用来打印警告信息')
    logger.error('error级别,一般用来打印一些错误信息')
    logger.critical('critical级别,一般用来打印一些致命的错误信息,等级最高')
    
if __name__ == '__main__':
    MyLogTest()
    

控制台输出:

2019-12-29 21:01:43,566 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:25] - INFO: info级别,一般用来打印一些正常的操作信息
2019-12-29 21:01:43,589 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:26] - WARNING: waring级别,一般用来打印警告信息
2019-12-29 21:01:43,608 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:27] - ERROR: error级别,一般用来打印一些错误信息
2019-12-29 21:01:43,623 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:28] - CRITICAL: critical级别,一般用来打印一些致命的错误信息,等级最高

MyLogTest.log文件输出:

2019-12-29 21:03:52,020 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:25] - INFO: info级别,一般用来打印一些正常的操作信息
2019-12-29 21:03:52,043 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:26] - WARNING: waring级别,一般用来打印警告信息
2019-12-29 21:03:52,051 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:27] - ERROR: error级别,一般用来打印一些错误信息
2019-12-29 21:03:52,056 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:28] - CRITICAL: critical级别,一般用来打印一些致命的错误信息,等级最高

如果想知道 logging 模块所在路径,Linux 下同样适用,适合于查看源代码,继承(改造)logging 模块

>>> import logging
>>> logging
<module 'logging' from 'C:\Python27\lib\logging\__init__.pyc'>

2. Python log 的日志级别

Python 标准库 logging 用作记录日志,默认分为六种日志级别(括号为级别对应的数值):

1)NOTSET(0)

2)DEBUG(10)

3)INFO(20)

4)WARNING(30)

5)ERROR(40)

6)CRITICAL(50)

 

我们自定义日志级别时注意不要和默认的日志级别数值相同,logging 执行时输出大于等于设置的日志级别的日志信息,如设置日志级别是 INFO,则 INFO、WARNING、ERROR、CRITICAL 级别的日志都会输出。

 

3.logging 日志格式

logging.basicConfig(format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s',
                    level=logging.DEBUG)
2019-07-19 15:54:26,625 - log_test.py[line:11] - DEBUG: debug级别,一般用来打印一些调试信息,级别最低

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

%(name)s:Logger的名字
%(levelno)s:打印日志级别的数值
%(levelname)s:打印日志级别的名称
%(pathname)s:打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s:打印当前执行程序名
%(funcName)s:打印日志的当前函数
%(lineno)d:打印日志的当前行号
%(asctime)s:打印日志的时间
%(thread)d:打印线程ID
%(threadName)s:打印线程名称
%(process)d:打印进程ID
%(message)s:打印日志信息

 

4.logging 模块:Logger 、Handler、Filter、Formatter

logging 库采取了模块化的设计,提供了许多组件:记录器、处理器、过滤器和格式化器

  • Logger 暴露了应用程序代码能直接使用的接口。
  • Handler 将(记录器产生的)日志记录发送至合适的目的地。
  • Filter 提供了更好的粒度控制,它可以决定输出哪些日志记录。
  • Formatter 指明了最终输出中日志记录的内容和格式。

简单地说,其中 logger 是负责记录日志消息的,然后我们要把这些日志消息放到哪里,交给 Handler 处理,Filter 则帮我们过滤信息(不限于通过级别过滤,意思是还有其他过滤方式),Formatter 就是跟上面的 format 一个意思,用来设置日志内容和格式。

Logger 负责记录日志

Handler 负责日志的处理(怎么输出,输出到哪里)

Formatter 控制日志的输出格式

Filter 日志的过滤控制

 

logger = logging.getLogger('test')
logger.setLevel(level=logging.DEBUG)

formatter = logging.Formatter('%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.DEBUG)
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)
...

我们发现Formatter是给handler设置的,这很好理解,因为handler是负责把日志输出到哪里,所以是给它设置格式,而不是给logger;那为什么level需要设置两次呢?给logger设置是告诉它要记录哪些级别的日志,给handler设是告诉它要输出哪些级别的日志,相当于进行了两次过滤。这样的好处在于,当我们有多个日志去向时,比如既保存到文件,又输出到控制台,就可以分别给他们设置不同的级别;logger 的级别是先过滤的,所以被 logger 过滤的日志 handler 也是无法记录的,这样就可以只改 logger 的级别而影响所有输出。两者结合可以更方便地管理日志记录的级别。
 

5.自动分割日志文件-日志文件按照时间划分或者按照大小划分

有时候我们需要对日志文件进行分割,以方便我们的管理。python 提供了两个处理器,方便我们分割文件:

logging.handlers.RotatingFileHandler -> 按照大小自动分割日志文件,一旦达到指定的大小重新生成文件
logging.handlers.TimedRotatingFileHandler -> 按照时间自动分割日志文件

如果将日志保存在一个文件中,那么时间一长,或者日志一多,单个日志文件就会很大,既不利于备份,也不利于查看。我们会想到能不能按照时间或者大小对日志文件进行划分呢?答案肯定是可以的,并且还很简单,logging 考虑到了我们这个需求。logging.handlers 文件中提供了 TimedRotatingFileHandlerRotatingFileHandler 类分别可以实现按时间和大小划分。打开这个 handles 文件,可以看到还有其他功能的 Handler 类,它们都继承自基类 BaseRotatingHandler

# TimedRotatingFileHandler 类构造函数
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None):
# RotatingFileHandler 类的构造函数
def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False)

示例代码:

1)按照日志文件的大小进行划分:

from logging import handlers

# 每隔 1000 Byte 划分一个日志文件,备份文件为 3 个
file_handler = logging.handlers.RotatingFileHandler("test.log", mode="w", maxBytes=1000, backupCount=3, encoding="utf-8")

2)按照日志的记录时间进行划分:

# 每隔 1小时 划分一个日志文件,interval 是时间间隔,备份文件为 10 个
handler2 = logging.handlers.TimedRotatingFileHandler("test.log", when="H", interval=1, backupCount=10)

若改为when='S',则以秒为周期进行切割,运行几次后会生成文件,文件名以时间为后缀进行区分,其中没有后缀的为最新日志文件。

 

6总结与扩展

Python logging 库设计的真的非常灵活,如果有特殊的需要还可以在这个基础的 logging 库上进行改进,创建新的 Handler 类解决实际开发中的问题。

Python 官网虽然说 logging 库是线程安全的,但在多进程、多线程、多进程多线程环境中仍然还有值得考虑的问题,比如,如何将日志按照进程(或线程)划分为不同的日志文件,也即一个进程(或线程)对应一个文件。

 

 

7 Linux 下的 rsyslog 日志服务器

 

[1]https://blog.csdn.net/paopaohll/article/details/84388313

 

8.参考

[1]https://blog.csdn.net/Runner1st/article/details/96481954

[2]https://cloud.tencent.com/developer/article/1354396

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值