• 【Python学习】logging日志模块


    一、logging模块介绍

      logging是Python中自带的标准模块,是Python中用来操作日志的模块。

    1、控制台输出日志

    复制代码
     1 import logging
     2 logging.basicConfig(level=logging.ERROR,  # 打印的日志级别
     3                     format=
     4                     '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
     5                     # 日志格式
     6                     )
     7 logging.debug('debug级别,最低级别,一般开发人员用来打印一些调试信息')
     8 logging.info('info级别,正常输出信息,一般用来打印一些正常的操作')
     9 logging.warning('waring级别,一般用来打印警信息')
    10 logging.error('error级别,一般用来打印一些错误信息')
    11 logging.critical('critical级别,一般用来打印一些致命的错误信息')
    复制代码

    日志级别 debug < info < warning < error < critical

      设置了日志级别之后,会打印该级别以及比该级别高的所有日志,举个例子,如果日志级别是warning,那么就会打印warning、error、critical,这三个级别的日志,不会打印debug和info级别的,如果是debug,最低级别的日志,那么所有的日志都会打印。
      上面的只是在控制台打印日志,并没有把日志写在文件里面,一般我们都会把日志写在日志文件里面,也很简单,只需要加个参数指定文件名就行了。

    2、把日志存入日志文件

      要把日志存入日志文件,需要加上filename参数(即日志文件名)以及filemode参数(写日志模式w为覆盖,a为追加),没有加filename参数时,控制台会输出日志信息,加了filename参数后,控制台不会再输出日志信息。

    复制代码
     1 import logging
     2 # 没有加filename参数时,控制台有输出日志信息,加了filename参数时,控制台不会再输出日志信息
     3 logging.basicConfig(level=logging.ERROR,  # 打印的日志级别
     4                     filename='my.log',    # 日志文件名
     5                     filemode='a',         # w清空,a追加写入,不会清空
     6                     format=
     7                     '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
     8                     # 日志格式
     9                     )
    10 logging.debug('debug级别,最低级别,一般开发人员用来打印一些调试信息')
    11 logging.info('info级别,正常输出信息,一般用来打印一些正常的操作')
    12 logging.warning('waring级别,一般用来打印警信息')
    13 logging.error('error级别,一般用来打印一些错误信息')
    14 logging.critical('critical级别,一般用来打印一些致命的错误信息')
    复制代码

    运行后发现能够生成日志文件,但日志文件里面的中文显示为乱码,且控制台不再打印日志信息。

    复制代码
     1 # 可以指定日志的输出格式format,这个参数可以输出很多有用的信息,如下面的几种格式:
     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:     # 打印日志信息
    13 # 常用格式:
    14 # format = '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
    15 # 这个格式可以输出日志的打印时间,是哪个文件第几行输出的,输出的日志级别是什么,以及输入的日志内容。
    复制代码

    3、同时实现控制台输出日志、写入日志文件

      logging模块中主要有4个类,分别负责不同的工作:

        (1)Logger记录器:暴露了应用程序代码能直接使用的接口。简单点说就是一个创建一个办公室,让人在里头工作 

        (2)Handler 处理器:将(记录器产生的)日志记录发送至合适的目的地。这个简单点说就是办事的人,你可以指定是让在控制输出日志,还是在文件里面打    印日志,常用的有4种:

            后面两种需要导入handlers,from logging import handlers

            a、StreamHandler 控制台输出

            b、FileHandler 文件输出

            c、TimedRotatingFileHandler 按照时间自动分割日志文件

            d、RotatingFileHandler 按照大小自动分割日志文件,一旦达到指定的大小重新生成文件

        (3)Filter过滤器:提供了更好的粒度控制,它可以决定输出哪些日志记录。(不常用)

        (4)Formatter格式化器:指明了最终输出中日志记录的布局。指定输出日志的格式

      具体怎么实现呢?得有个办公室,里面放两个人,一个负责往控制台输出日志,一个负责将日志写入日志文件。

    复制代码
     1 import logging
     2 from logging import handlers
     3 logger = logging.getLogger()    # 先实例化一个logger对象,先创建一个办公室
     4 logger.setLevel(logging.DEBUG)  # 设置日志的总级别
     5 # 创建一个文件处理器,也就是把日志写到文件里(fh的功能包含在th当中,所以fh可以删除不写)
     6 fh = logging.FileHandler(filename='my.log',mode='a',encoding='utf-8')
     7 fh.setLevel(logging.ERROR)      # 设定文件输出的日志级别
     8 # 创建一个控制台输出的处理器
     9 sh = logging.StreamHandler()
    10 sh.setLevel(logging.INFO)       # 设置控制台输出的日志级别
    11 # 创建一个指定间隔时间自动生成日志文件的处理器,这个相对于fh更好用
    12 th = handlers.TimedRotatingFileHandler(filename='a.log',when='S',interval=1,backupCount=3,encoding='utf-8')
    13 # interval是时间间隔,backupCount是备份文件的个数,如果超过这个超过这个个数,就会自动删除
    14 # when是间隔的时间单位,单位有以下几种:
    15     # S 秒
    16     # M 分
    17     # H 小时
    18     # D 天
    19     # W 星期(interval==0时代表星期一)
    20     # midnight 每天凌晨
    21 th.setLevel(logging.INFO)       # 设定自动生成日志文件的日志级别
    22 # 以上三个日志级别都可以单独设置,他们和总日志级别logger的级别区别是如果logger设置的级别比里面的handler级别设置的高,那么就以logger的级别为准
    23 # 指定日志格式
    24 formater = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')
    25 fh.setFormatter(formater)   # 设置文件处理器输出的日志格式
    26 sh.setFormatter(formater)   # 设置控制台输出的日志格式
    27 th.setFormatter(formater)   # 设置文件里面写入的日志格式
    28 # 把三个handler加入容器里头,相当于把工作人员培训完了,你们可以上班了
    29 logger.addHandler(fh)       # 把文件处理器放到办公室
    30 logger.addHandler(sh)       # 把控制台输出的处理器放到办公室
    31 logger.addHandler(th)       # 把第二个文件处理器放到办公室
    32 
    33 # 执行
    34 logger.debug('debug级别,最低级别,一般开发人员用来打印一些调试信息')
    35 logger.info('info级别,正常输出信息,一般用来打印一些正常的操作')
    36 logger.warning('waring级别,一般用来打印警信息')
    37 logger.error('error级别,一般用来打印一些错误信息')
    38 logger.critical('critical级别,一般用来打印一些致命的错误信息')
    复制代码

     二、封装写日志的类

    复制代码
     1 # 封装写日志的类
     2 import logging
     3 from logging import handlers
     4 class MyLogger():
     5     def __init__(self,file_name,level='info',backCount=5,when='D'):
     6         logger = logging.getLogger()            # 先实例化一个logger对象,先创建一个办公室
     7         logger.setLevel(self.get_level(level))  # 设置日志级别
     8         ch = logging.StreamHandler()            # 负责往控制台输出日志
     9         bh = handlers.TimedRotatingFileHandler(filename=file_name,when=when,interval=1,backupCount=backCount,encoding='utf-8')
    10         formater = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')
    11         ch.setFormatter(formater)   # 设置控制台输出的日志格式
    12         bh.setFormatter(formater)   # 设置文件里面写入的日志格式
    13         logger.addHandler(ch)       # 把把用于控制台输出的实例放入logger
    14         logger.addHandler(bh)       # 把用于写文件的实例放入logger
    15         self.logger = logger
    16     def get_level(self,str):        # 该函数把输入的字符串转换成日志级别(debug转换成logging.DEBUG)
    17         level = {
    18             'debug':logging.DEBUG,
    19             'info':logging.INFO,
    20             'waring':logging.WARNING,
    21             'error':logging.ERROR,
    22             'critical':logging.CRITICAL
    23         }
    24         str = str.lower()
    25         return level.get(str)
    26 
    27 mylog = MyLogger('my.log','debug')
    28 mylog.logger.warning('waring级别日志')
    复制代码

    三、第三方模块nnlog

      直接pip install nnlog即可,使用例子如下面代码:

    1 import nnlog
     2 # 实例化
     3 log = nnlog.Logger(file_name='my.log', level='debug', when='D', backCount=5, interval=1)
     4 # file_name是日志文件名
     5 # level是日志级别,如果不传的话默认是debug级别
     6 # when是日志文件多久生成一个,默认是按天,S 秒、M 分、 H 小时、 D 天、 W 每星期
     7 # backCount是备份几个日志文件,默认保留5天的
     8 # interval是间隔多久生成一个日志文件,默认是1天
     9 log.debug('默认日志级别是debug')
    10 log.info('info级别')
    11 log.warning('waring级别')
    12 log.error('error级别')

    实例

      1 #!/usr/bin/env python
      2 # encoding: utf-8
      3 import logging, os, time
      4 LOG_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "log")
      5 if not os.path.exists(LOG_DIR):
      6     try:
      7         os.mkdir(LOG_DIR)
      8     except Exception as e:
      9         print(e)
     10 
     11 
     12 
     13 class Logger(object):
     14     def __init__(self, cmd_level=logging.DEBUG, file_level=logging.DEBUG):
     15         log_file = time.strftime("%Y-%m-%d.log", time.localtime())
     16         path = os.path.join(LOG_DIR, log_file)
     17         self.logger = logging.getLogger(path)
     18         self.logger.setLevel(cmd_level)
     19         fmt = logging.Formatter('[%(asctime)s] [%(levelname)s] [%(pathname)s:%(lineno)d]%(message)s')
     20         # 设置文件日志
     21         fh = logging.FileHandler(path)
     22         fh.setFormatter(fmt)
     23         fh.setLevel(file_level)
     24         self.logger.addHandler(fh)
     25         # 设置CMD日志
     26         sh = logging.StreamHandler()
     27         sh.setFormatter(fmt)
     28         sh.setLevel(cmd_level)
     29         self.logger.addHandler(sh)
     30 
     31     def debug(self, msg, *args):
     32         try:
     33             if args:
     34                 msg = msg + ' ' + ' '.join(args)
     35             unicode_msg = msg.decode(encoding='utf-8', errors='ignore')
     36         except Exception:
     37             unicode_msg = msg
     38         self.logger.debug(msg=unicode_msg)
     39 
     40     def info(self, msg, *args):
     41         try:
     42             if args:
     43                 msg = msg + ' ' + ' '.join(args)
     44             unicode_msg = msg.decode(encoding='utf-8', errors='ignore')
     45         except Exception:
     46             unicode_msg = msg
     47         self.logger.info(msg=unicode_msg)
     48 
     49     def warn(self, msg, *args):
     50         try:
     51             if args:
     52                 msg = msg + ' ' + ' '.join(args)
     53             unicode_msg = msg.decode(encoding='utf-8', errors='ignore')
     54         except Exception:
     55             unicode_msg = msg
     56         self.logger.warn(msg=unicode_msg)
     57 
     58     def error(self, msg, *args):
     59         try:
     60             if args:
     61                 msg = msg + ' ' + ' '.join(args)
     62             unicode_msg = msg.decode(encoding='utf-8', errors='ignore')
     63         except Exception:
     64             unicode_msg = msg
     65         self.logger.error(msg=unicode_msg)
     66 
     67     def critical(self, msg, *args):
     68         try:
     69             if args:
     70                 msg = msg + ' ' + ' '.join(args)
     71             unicode_msg = msg.decode(encoding='utf-8', errors='ignore')
     72         except Exception:
     73             unicode_msg = msg
     74         self.logger.critical(msg=unicode_msg)
     75 
     76     def exception(self, msg, *args):
     77         try:
     78             if args:
     79                 msg = msg + ' ' + ' '.join(args)
     80             unicode_msg = msg.decode(encoding='utf-8', errors='ignore')
     81         except Exception:
     82             unicode_msg = msg
     83         self.logger.exception(msg=unicode_msg)
     84 
     85 logger = Logger().logger
     86 LOG_DEBUG = logger.debug
     87 LOG_INFO = logger.info
     88 LOG_WARN = logger.warn
     89 LOG_ERROR = logger.error
     90 LOG_EXCEPTION = logger.exception
     91 LOG_CRITICAL = logger.critical
     92 
     93 
     94 def title(title):
     95     LOG_INFO("=" * 10)
     96     LOG_INFO(title)
     97     LOG_INFO("=" * 10)
     98 
     99 
    100 # def step(step):
    101 #     LOG_INFO("*" * 10)
    102 #     LOG_INFO(step)
    103 #     LOG_INFO("*" * 10)
    104 
    105 
    106 TITLE = title
    107 # STEP = step
    108 
    109 
    110 if __name__ == '__main__':
    111     LOG_DEBUG("DEBUG")
    112     LOG_INFO("INFO")
    113     LOG_ERROR("ERROR")
    114     LOG_EXCEPTION("EXCEPTION")
    115     LOG_CRITICAL("CRITICAL")
    View Code
    作者:gtea 博客地址:https://www.cnblogs.com/gtea
  • 相关阅读:
    JAVA 注解的几大作用及使用方法详解
    内省、JavaBean、PropertyDescriptor类、Introspector类、BeanUtils工具包、注解、Rentention、Target、注解的基本属性和高级属性
    关于Hash集合以及Java中的内存泄漏
    ifconfig命令详情
    route命令详情
    ping命令详解
    scp命令详解
    ssh命令详解
    telnet命令详解
    sudo命令详解
  • 原文地址:https://www.cnblogs.com/gtea/p/12715357.html
Copyright © 2020-2023  润新知