python模块详解 | logging

基础日志 - logging.basicConfig()

日志基础教程

import logging

logging.basicConfig(
        filename='document.log',
        level=logging.INFO,
        format="%(asctime)s %(pathname)s[%(lineno)s]%(levelname)s:%(message)s",
        datefmt="%Y-%m-%d %H:%M:%S %p"
)

logging.info('记录到日志')

下面结合四个参数展开来聊一下,

1. filename

可选。保存到本地日志文件的文件名。

2. level

日志级别,各级别适用性如下(以严重性递增,DEBUG最低):

级别 优先级数值 何时使用
DEBUG 10 细节信息,仅当诊断问题时适用。
INFO 20 确认程序按预期运行
WARNING 30 表明有已经或即将发生的意外(例如:磁盘空间不足)。程序仍按预期进行
ERROR 40 由于严重的问题,程序的某些功能已经不能正常执行
CRITICAL 50 严重的错误,表明程序已不能继续执行

例:如果把日志记录级别设置为INFO,那么只有比日志是INFO或比INFO级别更高的日志,才会被记录到文件中

3. format

格式 描述
%(name)s 用于记录调用的日志记录器名称。
%(asctime)s 字符串形式的当前时间。 默认形式为 ‘2003-07-08 16:49:45,896’ (逗号之后的数字为时间的毫秒部分)
%(created)f 当前时间(即 time.time() 的返回值)
%(pathname)s 发出日志记录调用的「源文件的完整路径名」(如果可用)
%(filename)s 发出日志记录调用的「源文件的文件名」
%(funcName)s 调用日志输出函数的「函数名」
%(levelname)s 消息文本记录级别 ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL').
%(levelno)s 消息数字记录级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL).
%(lineno)d 发出日志记录调用所在的源代码「行号」(如果可用)
%(message)s 记入日志的消息
%(module)s 调用日志输出函数的模块名
%(process)d 进程ID,可能没有
%(thread)d 线程ID,可能没有

例:"%(asctime)s %(pathname)s[%(lineno)s]%(levelname)s:%(message)s"

4. datefmt

进阶日志 - logging.getLogger()

logging

进阶日志教程

1. Logger(记录器)

创建记录器对象

  • logger = logging.getLogger()

每个程序在输出信息之前都要获得一个logger,logger通常对应了程序的模块名。

记录器常见的配置方法:

2. Handler(处理程序)

https://docs.python.org/zh-cn/3.8/library/logging.handlers.html#watchedfilehandler

1. 创建处理程序对象,以下是一些常见的handler:

  • handler = logging.StreamHandler()

    class logging.StreamHandler(stream=None)

    StreamHandler 类位于核心 logging 包,它可将日志记录输出发送到数据流例如 sys.stdout, sys.stderr 或任何文件类对象(或者更精确地说,任何支持 write()flush() 方法的对象)

  • handler = logging.FileHandler()

    class logging.FileHandler(filename, mode=‘a’, encoding=None, delay=False)

    FileHandler 类位于核心 logging 包,它可将日志记录输出到磁盘文件中。 它从 StreamHandler 继承了输出功能。

  • handler = logging.NullHandler()

    NullHandler 类位于核心 logging 包,它不执行任何格式化或输出。 它实际上是一个供库开发者使用的‘无操作’处理程序。

  • handler = logging.handlers.WatchedFileHandler()

    WatchedFileHandler 类位于 logging.handlers 模块,这个 FileHandler 用于监视它所写入日志记录的文件。 如果文件发生变化,它会被关闭并使用文件名重新打开。

  • handler = logging.handlers.BaseRotatingHandler()

    BaseRotatingHandler 类位于 logging.handlers 模块中,它是轮换文件处理程序类 RotatingFileHandlerTimedRotatingFileHandler 的基类。 你不需要实例化此类,但它具有你可能需要重载的属性和方法。

  • handler = logging.handlers.RotatingFileHandler()

    class logging.handlers.RotatingFileHandler(filename, mode=‘a’, maxBytes=0, backupCount=0, encoding=None, delay=False)

    RotatingFileHandler 类位于 logging.handlers 模块,它支持磁盘日志文件的轮换。可以管理文件大小,当文件达到一定大小之后,它会自动将当前日志文件改名,让后创建一个新的同名日志文件继续输出。

  • handler = logging.handlers.TimedRotatingFileHandler()

    TimedRotatingFileHandler 类位于 logging.handlers 模块,它支持基于「特定时间间隔」的磁盘日志文件轮换。

    class logging.handlers.TimedRotatingFileHandler(filename, when=‘h’, interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None)

    • filename - 日志文件的保存路径

    • interval - 时间间隔

    • when - 时间间隔的单位

      间隔类型 如果/如何使用 atTime
      'S' 忽略
      'M' 分钟 忽略
      'H' 小时 忽略
      'D' 忽略
      'W0'-'W6' 工作日(0=星期一) 用于计算初始轮换时间
      'midnight' 如果未指定 atTime 则在午夜执行轮换,否则将使用 atTime 用于计算初始轮换时间

      注:

      1. 如果选择 D-天,那么这个不是严格意义上的“天”,而是从你项目启动开始,过了24小时,才会重新新建一个新的日志文件,如果项目重启,这个时间就会重置。
      2. 如果选择“midnight”, 指的是过了午夜12点,就会创建新的日志。
    • handler = logging.handlers.TimedRotatingFileHandler(log_path,
                                                     when='midnight',
                                                     interval=3,
                                                     backupCount=10,
                                                     encoding="utf-8")
      
  • 还有很多handler类型待发掘……

2. handler常见的配置方法:

  • handler.setLevel(level) - 指定被处理信息的信息等级

    • level - level = logging.INFO
  • handler.setFormatter(formatter) - 设置format格式

    • formatter - formatter = logging.Formatter(fmt, datefmt) fmt参数的使用请参考:format
  • handler.addFilter(filter)/removeFilter(filter) - 新增或删除一个filter对象

    • filter

      class IgnoreAssLogFilter(logging.Filter):
          # 忽略带ass的日志,
          def filter(self,record):
               return "ass" not in record.getMessage()
      
      handler.addFilter(IgnoreAssLogFilter())
      

3. logger + handler

import logging


# handler
handler = logging.FileHandler(filename="document.log")
handler.setLevel(logging.INFO)
handler.setFormatter(logging.Formatter('%(pathname)s %(message)s'))
# logger
logger = logging.getLogger('log')
logger.setLevel(logging.DEBUG)
logger.addHandler(handler) # 添加handler到logger
logger.info('我是日志内容,快把我记录下来')
import time
import logging
import logging.handlers


# formatter
formatter = logging.Formatter(
    fmt='%(asctime)s %(filename)s[%(lineno)d] %(levelname)s %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S')

# handler
handler_log = logging.handlers.TimedRotatingFileHandler(
  	filename=f'{time.strftime("%Y-%m-%d")}.log',
  	when='midnight',
  	interval=1,
  	encoding='utf-8'
)
handler_log.setLevel(logging.DEBUG)
handler_log.setFormatter(formatter)

handler_error = logging.FileHandler(filename='error.log')
handler_error.setLevel(logging.ERROR)
handler_error.setFormatter(formatter)

handler_console = logging.StreamHandler()
handler_console.setLevel(logging.INFO)
handler_console.setFormatter(formatter)

# logger
log = logging.getLogger('RPA')
log.setLevel(logging.DEBUG)
log.addHandler(handler_log)  # 日志文件
log.addHandler(handler_cs)  # console窗口

log.info('欲买桂花同载酒,终不似,少年游。')


1787 字