概述

Python logging 模块定义了为应用程序和库实现灵活的事件日志记录的函数和类,可以方便第三方模块或者是应用使用。这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET/POST,SMTP,Socket 等,甚至可以自定义实现具体的日志记录方式。

Logging 优点:

  • 使用 Python Logging 模块的主要好处是所有 Python 模块都可以参与日志记录
  • Logging 模块提供了大量具有灵活性的功能
  • 可以控制消息的级别,过滤掉那些并不重要的消息。

日志级别等级排序:critical > error > warning > info > debug

级别越高打印的日志越少,反之亦然。默认情况下日志打印只显示大于等于 WARNING 级别的日志。

日志记录的两种方式

Logging 模块提供了两种日志记录方式:

  • 方式1:使用 Logging 提供的模块级别的函数
  • 方式2:使用 Logging 日志系统的四大组件记录

logging 模块常用 API

  • debug(msg: str)、info(msg: str)、warning(msg: str)、error(msg: str) :生成不同级别的日志

  • basicConfig(**kwargs) :配置全局的日志系统参数,通常在应用程序的入口处调用。可以用于设置日志级别、输出格式、输出位置等参数。

    它接受一系列关键字参数(kwargs),以设置日志记录的行为。以下是一些常用参数

    • level :指定日志记录的最低级别。只有比该级别高或相同级别的消息才会被记录。

      可选级别包括 logging.DEBUG、logging.INFO、logging.WARNING、logging.ERROR 和 logging.CRITICAL

    • filename :指定日志输出的文件名。如果指定了此参数,日志将写入文件而不是默认的标准输出。

    • filemode :指定日志文件的打开模式,默认为 ‘a’(追加模式)。

      可以将其设置为 ‘w’(覆盖模式)或其他文件打开模式。

    • format :指定日志消息的输出格式。可以使用格式化字符串来定义输出的内容和样式

    • datefmt :指定日期和时间的格式。

      如果 format 中包含 %asctime%,则可以使用此参数自定义日期和时间的显示方式。

    • style :指定格式字符串的风格,可选值为 ‘%’ 和 ‘{’

      默认为 ‘%’,表示使用传统的 % 格式化风格。可以选择 ‘{’ 风格来使用更现代的 {} 格式。

    • handlers :指定用于处理日志消息的处理程序列表。

      可以将处理器直接传递给 handlers 参数,而不是使用 logger 的 addHandler() 方法添加

      注意:该参数会直接覆盖默认的标准输出处理器

  • getLogger(name: str) :用于创建和配置日志记录器(logger)。日志记录器用于在应用程序中生成日志消息,以便跟踪应用程序的运行和诊断问题。

    通常,可以为每个模块或子系统创建一个不同的记录器,以便更好地组织和管理日志消息。

    该方法通常接受一个名称参数,该参数用于指定要创建或获取的日志记录器的名称。logger 是单例的,如果多个模块使用相同的名称调用 getLogger,它们将获取到相同的记录器实例,从而实现日志消息的集中记录。

  • FileHandler(filename: str) :获取一个文件处理器(logging 模块提供的处理器 handler 之一),用于配置将日志消息写入指定的文件中,并根据需要配置级别和格式。

  • StreamHandler() :获取一个标准输出流处理器(logging 模块提供的处理器 handler 之一),用于配置将日志消息输出到标准输出流,通常是终端窗口或命令行界面,并根据需要配置级别和格式。

  • Formatter(format: str) : 获取 logging 模块提供的用于定义和格式化日志消息的输出格式的类对象。

    通过使用 Formatter,可以自定义日志消息的显示方式,包括日期时间、记录器名称、日志级别和消息内容等。

    常用自定义日志输出格式:'%(asctime)s [%(levelname)s] [%(threadName)s] [%(module)s.%(funcName)s.%(lineno)d] : %(message)s'

    日期和时间的格式:'%Y-%m-%d %H:%M:%S'

logging 的四大组件

简介

logging 模块采用了模块化设计,主要包含四种组件:

  • loggers:记录器,提供应用程序代码能直接使用的接口
  • handlers:处理器,将记录器产生的日志发送至目的地
  • filters:过滤器,提供更好的粒度控制,决定哪些日志会被输出
  • formatters:格式化器,设置日志内容的组成结构和消息字段

组件之间的关联关系

  • 记录器(logger)需要通过处理器(handler)将日志信息输出到目标位置,不同的处理器(handler)可以将日志输出到不同的位置;

    记录器(logger)可以设置多个处理器(handler)将同一条日志记录输出到不同的位置;

    每个处理器(handler)都可以设置自己的过滤器(filter)实现日志过滤,从而只保留感兴趣的日志;

    每个处理器(handler)都可以设置自己的格式器(formatter)实现同一条日志以不同的格式输出到不同的地方。

  • 简单来说:日志器(logger)是入口,真正干活儿的是处理器(handler),处理器(handler)还可以通过过滤器(filter)和格式器(formatter)对要输出的日志内容做过滤和格式化等处理操作。

  • 一个记录器(logger)可以包含一个或多个处理器(handler)和 过滤器(filter)

    一个处理器(handler)可以新增一个或多个格式器(formatter)和过滤器(filter),而且日志级别将会继承。

logger:记录器

常用方法:

  • debug(msg)、info(msg)、warning(msg)、error(msg) :生成不同级别的日志

  • setLevel() :设置记录器的日志级别,以确定哪些级别的日志消息会被记录。

    注:

    • 默认日志级别为 WARNING

    • 除了设置日志记录器的级别,还需要确保与该记录器关联的处理器的日志级别设置一致。

      如果处理器的级别高于记录器的级别,那么即使记录器级别足够低,也不会记录消息。

  • addFilter(filter) :添加一个过滤器,用于对日志消息进行额外的筛选和处理。

  • addHandler(handler) :添加一个日志处理器,指定如何处理日志消息,例如写入文件、打印到控制台等

  • removeFilter(filter) :从日志记录器中移除指定的过滤器。

  • removeHandler(handler) :从 logger 中移除指定的处理程序

handler:处理器

在 Python 的 logging 模块中,handlers(处理器)负责定义日志记录应输出到何处。处理器确定日志记录如何处理,无论是将它们发送到控制台、写入文件,还是甚至通过网络发送。

以下是 logging 模块提供的一些常见日志处理器

  • logging.StreamHandler :此处理程序将日志记录发送到一个流(stream),通常是控制台(stdout 或 stderr)。适用于在终端中显示日志消息。

  • logging.FileHandler :此处理程序将日志记录写入指定的日志文件。

    常用参数:

    • filename(必传):指定日志文件的基本名称

    • mode :指定打开文件的模式,默认为 ‘a’(追加模式)

      可以选择的模式包括:

      • ‘a’:追加模式,在文件末尾追加日志消息
      • ‘w’:写模式,每次写入日志消息时都会覆盖文件
  • logging.handlers.RotatingFileHandler :此处理程序允许在日志文件达到一定大小时进行“滚动”,创建一个新的日志文件。可以指定最大的日志文件大小,一旦达到该大小,就会创建一个新的日志文件。

    常用参数:

    • filename(必传):指定日志文件的名称

      轮换后的日志文件会以这个名称作为前缀,数字索引会被附加到名称中以创建不同的日志文件。

      例如,如果设置为 ‘my_log.log’,则生成的文件将类似于 ‘my_log.log’、‘my_log.log.1’、‘my_log.log.2’,以此类推。

    • mode :指定打开文件的模式,默认为 ‘a’(追加模式)

    • maxBytes :指定单个日志文件的最大字节数。一旦达到这个大小,会触发轮换并创建新的日志文件。

      默认值为 0,表示不限制日志文件的大小。

    • backupCount :指定要保留的旧日志文件的最大数量。一旦超过这个数量,最早的日志文件将被删除。

      默认值为 0,表示不保留旧日志文件。

    • encoding :指定日志文件的编码方式,默认为 None,表示使用系统默认编码。

  • logging.handlers.TimedRotatingFileHandler :此处理程序根据指定的时间间隔(如每天、每小时等)对日志文件进行轮换,可以根据时间来组织日志文件。

    常用参数:

    • filename(必传):指定日志文件的基本名称。轮换后的日志文件会以这个名称作为前缀,日期和时间戳会被附加到名称中以创建不同的日志文件

    • when :指定轮换的时间间隔。默认值为 H

      可选值包括:‘S’:秒,‘M’:分钟,‘H’:小时,‘D’:天,‘W0’ – ‘W6’:每周的某一天,其中 ‘W0’ 表示周日,‘W6’ 表示周六,‘midnight’:每天午夜。

    • interval :指定轮换的时间间隔大小。默认值为 1,表示每个 when 指定的时间单位都会触发一次轮换。

    • backupCount :指定在轮换期间要保留的旧日志文件的最大数量。一旦超过这个数量,最早的日志文件将被删除。

      默认值为 0,表示不保留旧日志文件。

    • encoding :指定日志文件的编码方式,默认为 None,表示使用系统默认编码。

    • atTime :可选参数,用于指定轮换的准确时间。

      当 when 设置为 ‘S’、‘M’、‘H’ 时,可以使用此参数来指定具体的时间,例如 ‘atTime=‘23:30:00’

  • logging.handlers.SocketHandler :将日志消息发送到网络套接字,可以用于将日志信息发送到远程服务器。

  • logging.handlers.SysLogHandler :将日志消息发送到系统日志,通常用于在 Unix 系统上记录系统事件。

  • logging.handlers.NTEventLogHandler :将日志消息发送到 Windows 事件日志,通常用于在 Windows 系统上记录事件。

handlers 处理器的一些常用的通用方法:

  • setLevel() :设置记录器的日志级别。只有达到或超过这个级别的日志消息才会被处理器处理。
  • setFormatter(fmt: Formatter) :设置处理器的日志消息格式化器
  • **addFilter(filter) ** :添加一个过滤器(filter)到处理器。过滤器用于更细粒度地控制哪些日志消息会被处理。
  • removeFilter(filter) :从处理器中移除指定的过滤器。

filter:过滤器

在 Python 的 logging 模块中,Filter 类用于过滤日志消息,允许更细粒度地控制哪些日志消息会被处理器处理。

可以自定义一个或多个过滤器,并将它们添加到处理器或记录器中,以仅允许满足特定条件的日志消息被记录或处理。

一些常见的内置过滤器:

  • logging.Filter:一个通用的基类过滤器,可以继承它并实现自定义的 filter(record) 方法来控制哪些日志消息会被处理。

    这是一个灵活的过滤器,可以用于满足各种不同的需求。

    # 自定义过滤器class MyFilter(logging.Filter):def filter(self, record):# 只有级别为 WARNING 及以上的日志消息才会被记录return record.levelno >= logging.WARNING# 创建一个自定义过滤器并添加到处理器my_filter = MyFilter()handler.addFilter(my_filter)
  • logging.FilterByLevel(level):根据日志级别筛选日志消息的过滤器。

    可以指定最低的日志级别,只有达到或超过该级别的日志消息才会被处理。

    例如,如果要仅记录级别为 WARNING 及以上的日志消息,可以使用如下方式:

    filter = logging.FilterByLevel(logging.WARNING)
  • logging.FilterByName(name):根据记录器名称筛选日志消息的过滤器。

    可以使用此过滤器指定特定记录器的日志消息是否应该被处理。

    例如,如果要仅记录名为 “my_logger” 的记录器的日志消息,可以使用如下方式:

    filter = logging.FilterByName('my_logger')
  • logging.FilterByValue(key, value):根据日志记录中的属性键和值来筛选日志消息。

    只有具有指定键和值的属性的日志消息才会被处理。

formatter:格式化器

在 Python 的 logging 模块中,Formatter 类用于定义日志消息的输出格式。

通过使用格式化器,可以自定义日志消息的外观,以包括时间戳、日志级别、日志名称、消息文本等信息。

以下是一些常见的格式化占位符,可以用于创建自定义格式化器:

  • %(asctime)s :字符串形式的当前时间。默认格式是 “%Y-%m-%d %H:%M:%S,sss”,其中 %Y 表示年份、%m 表示月份、%d 表示日期、%H 表示小时、%M 表示分钟、%S 表示秒钟、sss 表示毫秒

  • %(levelname)s :文本形式的日志级别

  • %(levelno)s :数字形式的日志级别

  • %(message)s :用户输出的消息

    注:显式指定毫秒会报错,原因未知。若需要打印毫秒级的时间,使用默认即可,不要显式指定时间格式

  • %(name)s :Logger(记录器)的名字

  • %(pathname)s :调用日志输出函数的模块的完整路径名,可能没有

  • %(filename)s :调用日志输出函数的模块的文件名

  • %(module)s :调用日志输出函数的模块名

  • %(funcName)s :调用日志输出函数的函数名

  • %(lineno)d :调用日志输出函数的语句所在的代码行

  • %(created)f :当前时间,用 UNIX 标准的表示时间的浮点数表示,通常是从 Epoch 时间(1970年1月1日起的秒数)

  • %(relativeCreated)d :输出日志信息时的,自 Logger 创建以来的毫秒数

  • %(thread)d :线程 ID。可能没有

  • %(threadName)s :线程名。可能没有

  • %(process)d :进程 ID。可能没有

代码示例

import loggingimport socketimport oslog_format = '%(asctime)s [%(levelname)s] [%(threadName)s] [%(module)s.%(funcName)s.%(lineno)d] : %(message)s'# 配置全局的日志系统参数logging.basicConfig(level='DEBUG', format=log_format)file_dir = './log'if not os.path.exists(file_dir):os.makedirs(file_dir)# 使用主机名作为日志文件名称file_name = os.path.join(file_dir, socket.gethostname() + ".log")# 创建一个处理器,将日志写入文件file_handler = logging.FileHandler(os.path.join(file_name))file_handler.setFormatter(logging.Formatter(log_format))# 将日志文件处理器加入到默认记录器中logging.getLogger().addHandler(file_handler)name = "ZhangSan"logging.debug(f"my name is {name}")