IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Python笔记之logging【一】 -> 正文阅读

[Python知识库]Python笔记之logging【一】

本文为博主原创,未经授权,严禁转载及使用。
本文链接:https://blog.csdn.net/zyooooxie/article/details/123635856

很早之前在跑脚本时,我都是用print() 来输出、展示数据,方便是方便,但 就是一次性(没法保存,用来追溯);后面 我了解到logging,最近做了些学习后,分享下。

【实际这篇博客推迟发布N个月】

个人博客:https://blog.csdn.net/zyooooxie

【以下所有内容仅为个人项目经历,如有不同,纯属正常】

logging

https://docs.python.org/zh-cn/3.8/library/logging.html
https://docs.python.org/zh-cn/3.8/howto/logging.html
https://docs.python.org/zh-cn/3.8/howto/logging-cookbook.html

https://docs.python.org/zh-cn/3.8/library/logging.html#logrecord-attributes

"""
@blog: https://blog.csdn.net/zyooooxie
@qq: 153132336
"""

import logging.handlers
import logging
import logging.config
import time

abc = time.strftime('%Y%m%d_%H%M%S', time.localtime(time.time()))

# 关于流程:很多行日志 Log Record -> 日志记录器 Logger -> Logger 收集日志的等级 -> 处理程序 Handler -> Handler 输出日志的等级 -> 输出到 控制台|文件


def test_10():
    # 日志功能应以所追踪事件级别或严重性而定。
	
    # 各级别适用性如下(以严重性递增):
    # DEBUG         细节信息,仅当诊断问题时适用。
    # INFO          确认程序按预期运行
    # WARNING       表明有已经或即将发生的意外(例如:磁盘空间不足)。程序仍按预期进行
    # ERROR         由于严重的问题,程序的某些功能已经不能正常执行
    # CRITICAL      严重的错误,表明程序已不能继续执行

    # 输出到命令行。INFO 消息并没有出现,因为默认级别是WARNING。
    logging.debug('debug日志')
    logging.info('info日志')
    logging.warning('warning日志')
    logging.error('error日志')
    logging.critical('critical日志')

    # 要记录变量数据,请使用格式字符串作为事件描述消息,并将变量数据作为参数附加。
    logging.critical('critical,%s,%s', '123456', 123456789)  # 将可变数据合并到事件描述消息中使用旧的%s 形式的字符串格式化


def test_11():
    # 整个日志记录的框架可以分为这么几个部分:

    # Logger:即 Logger Main Class,是我们进行日志记录时创建的对象,我们可以调用它的方法传入日志模板和信息,来生成一条条日志记录。
    # Log Record:就代指生成的一条条日志记录。
    # Handler:即用来处理日志记录的类,它可以将 Log Record 输出到我们指定的日志位置和存储形式等,如:我们可以指定将日志通过 FTP 协议记录到远程的服务器上,Handler 就会帮我们完成这些事情。
    # Formatter:实际上生成的 Log Record 也是一个个对象,那么我们想要把它们保存成一条条我们想要的日志文本的话,就需要有一个格式化的过程,那么这个过程就由 Formatter 来完成,返回的就是日志字符串,然后传回给 Handler 来处理。
    # Filter:另外保存日志的时候我们可能不需要全部保存,我们可能只需要保存我们想要的部分就可以了,所以保存前还需要进行一下过滤,留下我们想要的日志,如只保存某个级别的日志,或只保存包含某个关键字的日志等,那么这个过滤过程就交给 Filter 来完成。
    # Parent Handler:Handler 之间可以存在分层关系,以使得不同 Handler 之间共享相同功能的代码。

    pass

"""
@blog: https://blog.csdn.net/zyooooxie
@qq: 153132336
"""

def test_0():
    # 日志事件信息 在LogRecord实例中的记录器、处理程序、过滤器和格式化程序之间传递。

    # 通过调用Logger类(以下称为loggers ,记录器)的实例来执行日志记录。每个实例都有一个名称,它们在概念上以点(句点)作为分隔符排列在命名空间的层次结构中。

    # 注意 永远不要直接实例化记录器 (class logging.Logger),应当通过模块级别的函数 logging.getLogger(name) 。
    # 多次使用相同的名字调用getLogger() 会一直返回相同的Logger 对象的引用。
    # 这不仅是在同一个模块中,在其他模块调用也是如此,只要是在同一个Python 解释器进程中,是应该引用同一个对象。

    # 在命名记录器时使用的一个好习惯 是 在每个使用日志记录的模块中使用模块级记录器,命名如下:
    # logger = logging.getLogger(__name__)

    # 记录器层次结构的根称为根记录器。根记录器的名称在记录的输出中打印为’root’。

    # --------

    # 默认情况下,没有为任何日志记录消息设置目标。你可以使用basicConfig() 指定目标(例如控制台或文件)。
    # 如果你调用函数debug() 、info() 、warning() 、error() 和critical() ,他们将检查是否有设置目的地;
    # 如果没有设置,它们将在委托给根记录器进行实际的消息输出之前设置目标为 控制台(sys.stderr)和默认格式的显示消息。

    # 由basicConfig() 设置的消息默认格式为:severity:logger name:message,
    # BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
    # 通过使用format 参数将格式字符串传递给 basicConfig() 来更改此设置。

    # logging.basicConfig(**kwargs)
    # 通过使用默认的Formatter 创建一个StreamHandler 并将其加入根日志记录器来为日志记录系统执行基本配置。

    # 如果没有为根日志记录器定义处理程序,则debug(), info(), warning(),error() 和critical() 等函数将自动调用basicConfig()。
    # 如果根日志记录器已配置了处理程序,则此函数将不执行任何操作,除非关键字参数force 被设为True。

    # 支持以下关键字参数:
    # filename          使用指定的文件名,而不是StreamHandler 创建FileHandler。
    # filemode          如果指定了filename,则用此模式打开该文件。默认模式为'a'。          有两种形式,一种是 w,一种是 a,分别代表清除后写入和追加写入。
    # format            使用指定的格式字符串作为处理程序。默认为 以冒号分隔的levelname, name和message。
    # datefmt           使用指定的日期/时间格式,与time.strftime() 所接受的格式相同。
    # style             如果指定了format,将为格式字符串使用此风格。'%', '{' 或'$' 分别对应于printf 风格, str.format() 或string.Template。默认为'%'。
    # level             指定日志输出的类别,程序会输出大于等于此级别的信息。
    # stream            使用指定的流初始化StreamHandler。请注意此参数与filename 是不兼容的- 如果两者同时存在,则会引发ValueError。
    # handlers          如果指定,这应为一个包含要加入根日志记录器的已创建处理程序的可迭代对象。任何尚未设置格式描述符的处理程序将被设置为在此函数中创建的默认格式描述符。请注意此参数与filename 或stream 不兼容——如果两者同时存在,则会引发ValueError。
    # force             如果将此关键字参数指定为true,则在执行其他参数指定的配置之前,将移除并关闭附加到根记录器的所有现有处理器。

    pass


def test_1():
    # 记录器对象上使用最广泛的方法分为两类:配置和消息发送。

    # Logger.setLevel() 指定记录器将处理的最低严重性日志消息,其中debug 是最低内置严重性级别,critical 是最高内置严重性级别。
    # 例如,如果严重性级别为INFO ,则记录器将仅处理INFO 、 WARNING 、ERROR 和CRITICAL 消息,并将忽略DEBUG 消息。

    # Logger.addHandler() 和Logger.removeHandler() 从记录器对象中添加和删除处理程序对象。

    # Logger.addFilter() 和Logger.removeFilter() 可以添加或移除记录器对象中的过滤器。

    # getLogger() 返回对具有指定名称的记录器实例的引用(如果已提供),或者如果没有则返回root 。
    # 名称是以句点分隔的层次结构。多次调用getLogger() 具有相同的名称将返回对同一记录器对象的引用。

    # 记录器具有有效等级的概念。如果未在记录器上显式设置级别,则使用其父级别作为其有效级别。如果父级没有明确的级别设置,则检查其父级。依此类推,搜索所有上级元素,直到找到明确设置的级别。
    # 根记录器始终具有显式级别集(默认情况下为WARNING)

    # 以下方法将创建日志消息:
    # Logger.debug() 、Logger.info() 、Logger.warning() 、Logger.error() 和Logger.critical() 都创建日志记录,包含消息和与其各自方法名称对应的级别。
    # 该消息实际上是一个格式化字符串,它可能包含标题字符串替换语法%s 、%d 、%f 等等。其余参数是与消息中的替换字段对应的对象列表。

    # Logger.exception() 能创建与Logger.error() 相似的日志信息。不同之处是,Logger.exception() 同时还记录当前的堆栈追踪。仅从异常处理程序调用此方法。
    # 看源码:self.error(msg, *args, exc_info=exc_info, **kwargs)

    # logging.debug(), info(),error () 等方法中 如果exc_info 的求值结果不为false,则它将异常信息添加到日志消息中,如果提供了一个异常元组(按照sys.exc_info() 返回的格式)或一个异常实例,则将其使用;否则,调用sys.exc_info() 以获取异常信息。
    # 第二个可选关键字参数是stack_info,默认为False。如果为True,则将堆栈信息添加到日志消息中,包括实际的日志调用。请注意,这与通过指定exc_info 显示的堆栈信息不同:前者是从堆栈底部到当前线程中的日志记录调用的堆栈帧,而后者是在搜索异常处理程序时,跟踪异常而打开的堆栈帧的信息。

    # Logger.log() 将日志级别作为显式参数。对于记录消息而言,这比使用上面列出的日志级别方便方法更加冗长,但这是自定义日志级别的方法。

    pass



def test_2():
    # Handler 对象负责将适当的日志消息(基于日志消息的严重性)分派给处理程序的指定目标。Logger对象可以使用addHandler() 方法向自己添加零个或多个处理程序对象。

    # 注意不要直接实例化Handler ;这个类用来派生其他更有用的子类。
    # 主要介绍:
    # StreamHandler 实例发送消息到流,可以是 sys.stderr,sys.stdout 或者文件。
    # FileHandler 实例将消息发送到硬盘文件。
    # BaseRotatingHandler 是轮换日志文件的处理程序的基类。它并不应该直接实例化,而应该使用RotatingFileHandler 或TimedRotatingFileHandler 代替它。
    # RotatingFileHandler 实例将消息发送到硬盘文件,支持最大日志文件大小和日志文件轮换。
    # TimedRotatingFileHandler 实例将消息发送到硬盘文件,以特定的时间间隔轮换日志文件。


    # setLevel() 方法,就像在记录器对象中一样,指定将被分派到适当目标的最低严重性。为什么有两个setLevel() 方法?
    # Logger中设置的级别 决定它将传递给Handler的消息严重性。
    # 每个Handler设置的setLevel() 决定了该处理程序将发送哪些消息。


    # setFormatter() 选择一个该处理程序使用的Formatter 对象。
    # addFilter() 和removeFilter() 分别在处理程序上配置和取消配置过滤器对象。

    pass

def test_3():
    # 格式化程序对象配置日志消息的最终顺序、结构和内容。

    # 基础的Formatter 允许指定格式字符串。如果未提供任何值,则使用默认值'%(message)s' ,它仅将消息包括在日志记录调用中。

    # 构造函数有三个可选参数--消息格式字符串、日期格式字符串和样式指示符。
    # logging.Formatter.__init__(fmt=None, datefmt=None, style=’%’)
    # 如果没有消息格式字符串,则默认使用原始消息。
    # 如果没有日期格式字符串,则默认日期格式为:%Y-%m-%d %H:%M:%S,最后加上毫秒数。          使用格式’%Y-%m-%d %H:%M:%S,uuu’,其中uuu部分是毫秒值。

    # style 是%,’{ ’ 或’$’ 之一。如果未指定其中一个,则将使用’%’。如果style 是’%’,则消息格式字符串使用%(<dictionary key>)s 样式字符串替换;

    pass



def test_dictConfig():

    # logging.config.dictConfig(config)
    # 从一个字典 config 获取日志记录配置。字典的内容描述见下文的配置字典架构。


    # 传给dictConfig() 的字典必须包含以下的键:
    # ? version - 应设为代表架构版本的整数值。目前唯一有效的值是1。


    # 所有其他键都是可选项,但如存在它们将根据下面的描述来解读:
    # ? formatters - 对应的值将是一个字典,其中每个键是一个格式器ID 而每个值则是一个描述如何配置相应Formatter 实例的字典。将在配置字典中搜索键format 和datefmt (默认值均为None) 并且这些键会被用于构造Formatter 实例。
    # 【其值是一个字典对象,该字典对象每个元素的key为要定义的格式器名称,value为格式器的配置信息组成的dict,dict的key 包括如format和datefmt】


    # ? handlers - 对应的值将是一个字典,其中每个键是一个处理程序ID 而每个值则是一个描述如何配置相应Handler 实例的字典。
    # 将在配置字典中搜索下列键:
    # – class (强制)。这是处理程序类的完整限定名称。
    # – level (可选)。处理程序的级别。
    # – formatter (可选)。处理程序所对应格式化器的ID。
    # – filters (可选)。由处理程序所对应过滤器的ID 组成的列表。
    # 所有其他键会被作为关键字参数传递给处理程序类的构造器。
    # 【其值是一个字典对象,该字典对象每个元素的key为要定义的处理器名称,value为处理器的配置信息组成的dcit,如class、level、formatter和filters,其中class为必选项,其它为可选项;
    # 其他配置信息将会传递给class所指定的处理器类的构造函数,如下面的handlers定义示例中的stream、filename、maxBytes和backupCount等】


    # ? filters - 对应的值将是一个字典,其中每个键是一个过滤器ID 而每个值则是一个描述如何配置相应Filter 实例的字典。将在配置字典中搜索键name (默认值为空字符串) 并且该键会被用于构造logging.Filter 实例。
    # 【其值是一个字典对象,该字典对象每个元素的key为要定义的过滤器名称,value为过滤器的配置信息组成的dict,如name】


    # ? loggers - 对应的值将是一个字典,其中每个键是一个日志记录器名称而每个值则是一个描述如何配置相应Logger 实例的字典。
    # 将在配置字典中搜索下列键:
    # – level (可选)。日志记录器的级别。
    # – propagate (可选)。日志记录器的传播设置。
    # – filters (可选)。由日志记录器对应过滤器的ID 组成的列表。
    # – handlers (可选)。由日志记录器对应处理程序的ID 组成的列表。
    # 指定的日志记录器将根据指定的级别、传播、过滤器和处理程序来配置。
    # 【其值是一个字典对象,该字典对象每个元素的key为要定义的日志器名称,value为日志器的配置信息组成的dcit,如level、handlers、filters 和 propagate】


    # ? root - 这将成为根日志记录器对应的配置。配置的处理方式将与所有日志记录器一致,除了propagate 设置将不可用之外。
    # 【这是root logger的配置信息,其值也是一个字典对象。除非在定义其它logger时明确指定propagate值为no,否则root logger定义的handlers都会被作用到其它logger上】

    pass


def test_fileConfig():
    # logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True)
    # 从一个configparser 格式文件中读取日志记录配置。文件格式应当与配置文件格式中的描述一致。
    # 此函数可在应用程序中被多次调用,以允许最终用户在多个预设配置中进行选择(如果开发者提供了展示选项并加载选定配置的机制)。

    # fileConfig() 所能理解的配置文件格式是基于configparser 功能的。
    # fileConfig()函数所能理解的配置文件基础格式 是 与ConfigParser/configparser模块一致的,只是在此基础上对文件中包含的section和option做了一下规定和限制,
    # 该文件必须包含[loggers],[handlers] 和[formatters] 这些section,它们通过名称来标识文件中定义的每种类型的实体。对于每个这样的实体,都有单独的小节来标识实体的配置方式。

    # loggers这个section中的keys一定要包含root这个值。

    # 因此,对于[loggers] 小节中名为log01 的日志记录器,相应的配置详情保存在[logger_log01] 小节中。
    # 类似地,对于[handlers] 小节中名为hand01 的处理程序,其配置将保存在名为[handler_hand01] 的小节中,
    # 而对于[formatters]小节中名为form01 的格式化器,其配置将在名为[formatter_form01] 的小节中指定。
    # 根日志记录器的配置必须在名为[logger_root] 的小节中指定。

    # [logger_root] 根日志记录器必须指定一个级别 level 和一个处理程序列表 handlers。
    # level 条目可以为DEBUG, INFO, WARNING, ERROR, CRITICAL 或NOTSET 之一。其中NOTSET仅适用于根日志记录器,表示将会记录所有消息。
    # handlers 条目是以逗号分隔的处理程序名称列表,它必须出现于[handlers] 小节并且在配置文件中有相应的小节。

    # 对于 非root logger,还需要某些附加信息:
    # propagate 条目设为1 表示消息必须从此日志记录器传播到更高层级的处理程序,设为0 表示消息不会传播到更高层级的处理程序。
    # qualname 条目是日志记录器的层级通道名称,也就是应用程序 获取日志记录器所用的名称。

    # 指定处理程序配置的小节说明如下:  [handler_hand01]
    # class 条目指明 处理程序的类(由logging 包命名空间中的eval() 来确定)。
    # level 会以与日志记录器相同的方式来解读,NOTSET 会被视为表示‘记录一切消息’。
    # formatter 条目指明此处理程序的格式化器的键名称。如为空白,则会使用默认的格式化器(logging._defaultFormatter)。如果指定了名称,则它必须出现于[formatters] 小节并且在配置文件中有相应的小节。
    # args 条目,当在logging 包命名空间的上下文中执行eval() 时 将是 传给处理程序类构造器的参数列表。如果未提供,则默认为()。           它必须是一个元组(tuple)的形式
    # 可选的kwargs 条目,当在logging 包命名空间的上下文中执行eval() 时将是传给处理程序的构造器的关键字参数字典。如果未提供,则默认为{}。

    # 指定格式化器配置的小节说明如下:      [formatter_form01]
    # format 是整个格式字符串,
    # datefmt 条目则是兼容strftime() 的日期/时间格式字符串。如果为空,此包将替换任何接近于日期格式字符串'%Y-%m-%d %H:%M:%S' 的内容。此格式还指定了毫秒,并使用逗号分隔符将其附加到结果当中。此格式的时间示例如2003-01-23 00:29:50,411。
    # class 条目是可选的。它指明格式化器类的名称(形式为带点号的模块名加类名。)此选项适用于 实例化Formatter 的子类。

    # fileConfig() API 比dictConfig() API 更旧因而没有提供涵盖日志记录特定方面的功能。
    # 例如,你无法配置Filter 对象,该对象使用fileConfig() 提供超出简单整数级别的消息过滤功能。如果你想要在你的日志记录配置中包含Filter 的实例,你将必须使用dictConfig()。

    pass

"""
@blog: https://blog.csdn.net/zyooooxie
@qq: 153132336
"""

def test_0_a():
    # 对basicConfig() 的调用应该在debug() ,info() 等的前面。因为它被设计为 一次性的配置 ,只有第一次调用会进行操作,随后的调用不会产生有效操作。

    # logging.debug('debug日志111')
    # logging.info('info日志111')
    # logging.warning('warning日志111')
    # logging.error('error日志111')
    # logging.critical('critical日志111')

    # 要更改用于显示消息的格式,你需要 指定 要使用的格式:
    # https://docs.python.org/zh-cn/3.8/library/logging.html#logrecord-attributes
    logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s', level=logging.DEBUG)

    logging.debug('debug日志')
    logging.info('info日志')
    logging.warning('warning日志')
    logging.error('error日志')
    logging.critical('critical日志')


def test_0_b():
    # 需要更多地控制日期/时间的格式,请为basicConfig 提供datefmt 参数
    logging.basicConfig(format='%(asctime)s:%(message)s', level=logging.WARNING, datefmt='%m/%d/%Y %I:%M:%S %p')

    logging.debug('debug日志')
    logging.info('info日志')
    logging.warning('warning日志')
    logging.error('error日志')
    logging.critical('critical日志')


def test_0_c():
    # 将日志事件记录到文件
    logging.basicConfig(filename='example_1025001.log', level=logging.INFO, format='%(asctime)s:%(message)s')
    logger = logging.getLogger(__name__)

    logger.debug('debug日志')
    logger.info('info日志')
    logger.warning('warning日志')
    logger.error('error日志')
    logger.critical('critical日志')
    logger.critical('{}'.format(abc))

    # 如果多次运行上述脚本,则连续运行的消息将追加到文件example.log 。


def test_0_d():
    # 如果你希望每次运行重新开始,而不是记住先前运行的消息,则可以通过将上例中的调用更改为来指定filemode 参数:
    logging.basicConfig(filename='example_1025003.log', level=logging.ERROR, filemode='w',
                        # datefmt='%m/%d/%Y %I:%M:%S %p')
                        datefmt='%m/%d/%Y %I:%M:%S %p', format='%(asctime)s ** %(message)s')

    # 单传datefmt,不传format,还是走默认的format;datefmt 改的是 asctime

    logger = logging.getLogger(__name__)

    logger.info('info日志')
    logger.warning('warning日志')
    logger.error('error日志')
    logger.critical('critical日志')
    logger.critical('{}'.format(abc))


def test_1_a():
    logger = logging.getLogger(__name__)
    logger.setLevel(level=logging.DEBUG)

    # Formatter
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    # StreamHandler
    stream_handler = logging.StreamHandler()
    stream_handler.setFormatter(formatter)
    logger.addHandler(stream_handler)

    try:
        result = 10 / 0
    except Exception:
        # exc_info: 其值为布尔值,如果该参数的值设置为True,则会将异常异常信息添加到日志消息中。如果没有异常信息则添加None到日志信息中。

        logger.debug('Faild-debug', exc_info=True)
        logger.info('Faild-info', exc_info=True)
        logger.error('Faild-error', exc_info=True)
        logger.warning('Faild-warning', exc_info=True)
        logger.critical('Faild-critical', exc_info=True)

        logger.info('-----')

        # stack_info: 其值也为布尔值,默认值为False。如果该参数的值设置为True,栈信息将会被添加到日志信息中。
        logger.debug('Faild-debug', exc_info=True, stack_info=True)
        logger.info('Faild-info', exc_info=True, stack_info=True)
        logger.error('Faild-error', exc_info=True, stack_info=True)
        logger.warning('Faild-warning', exc_info=True, stack_info=True)
        logger.critical('Faild-critical', exc_info=True, stack_info=True)

    # -----

    logger.info('-----')

    try:
        result = 10 / 0
    except Exception:
        logger.exception('Faild-exception')  # 其实就是 logger.error('Faild-exception', exc_info=True)

    # -----

    logger.error('Faild222')

    logger.exception('Faild222')

    logger.log(logging.DEBUG, "This is a debug log.")
    logger.log(logging.INFO, "This is a info log.")
    logger.log(logging.WARNING, "This is a warning log.")
    logger.log(logging.ERROR, "This is a error log.")
    logger.log(logging.CRITICAL, "This is a critical log.")

    logger.info('-----')

    logger.log(10, "a debug log.")
    logger.log(20, "a info log.")
    logger.log(30, "a warning log.")
    logger.log(40, "a error log.")
    logger.log(50, "a critical log.")

    logger.log(45, "这是啥level")
    logger.log(500, "这是啥level")


def test_2_a():
    # 希望当 日志文件不断记录增长至一定大小时,打开一个新的文件接着记录。
    # 你可能希望只保留一定数量的日志文件,当不断的创建文件到达该数量时,又覆盖掉最开始的文件形成循环。
    # 对于这种使用场景,日志包提供了RotatingFileHandler:

    LOG_FILENAME = '2_a.log'

    my_logger = logging.getLogger('MyLogger')
    # my_logger.setLevel(logging.WARNING)
    my_logger.setLevel(logging.WARN)
    # WARNING 还提供了简写形式 WARN

    # Add the log message handler to the logger
    handler = logging.handlers.RotatingFileHandler(
        LOG_FILENAME, maxBytes=10, backupCount=5)
    my_logger.addHandler(handler)

    # 你可以使用maxBytes 和backupCount 值来允许文件以预定的大小执行rollover。当即将 超出预定大小 时,将关闭旧文件并打开一个新文件用于输出。
    # 只要当前日志文件长度接近maxBytes 就会发生轮换;但是如果maxBytes 或backupCount 两者之一的值为零,就不会发生轮换,因此你通常要设置backupCount 至少为1,而maxBytes 不能为零。
    # 当backupCount 为非零值时,系统将通过为原文件名添加扩展名’.1’, ’.2’ 等来保存旧日志文件。

    # 例如,当backupCount 为5 而基本文件名为app.log 时,你将得到app.log, app.log.1, app.log.2 直至app.log.5。当前被写入的文件总是app.log。
    # 当此文件写满时,它会被关闭并重户名为app.log.1,而如果文件app.log.1, app.log.2 等存在,则它们会被分别重命名为app.log.2, app.log.3 等等。

    # 内容最新的排序:app.log, app.log.1, app.log.2 直至app.log.5

    my_logger.debug('debug日志')
    my_logger.info('info日志')
    my_logger.warning('warning日志')
    my_logger.error('error日志')
    my_logger.critical('critical日志')

    my_logger.critical('{}'.format(abc))

    my_logger.debug('debug日志111')
    my_logger.info('info日志111')
    my_logger.warning('warning日志111')
    my_logger.error('error日志111')
    my_logger.critical('critical日志111')
    

def test_2_b():
    # TimedRotatingFileHandler 类位于logging.handlers模块,它支持 基于特定时间间隔的磁盘日志文件轮换。

    # 轮换的发生是基于when 和interval 的积。
    # 源码:self.interval = self.interval * interval # multiply by units requested

    # 可以使用when 来指定interval 的类型。interval是时间间隔,when是间隔的时间单位。
    # 可能的值列表如下。请注意 它们不是大小写敏感的,lower or upper case will work。
    # S     秒
    # M     分
    # H     小时
    # D     天
    # W{0-6}     工作日(W0= 星期一)
    # midnight          每天凌晨

    # elif self.when == 'D' or self.when == 'MIDNIGHT':
    # self.interval = 60 * 60 * 24  # one day

    when_ = 'd'
    interval_ = 1

    # 如果backupCount 不为零,则最多将保留backupCount 个文件,而如果当轮换发生时创建了更多的文件,则最旧的文件会被删除。
    # 删除逻辑使用间隔时间来确定要删除的文件,因此改变间隔时间可能导致旧文件被继续保留。
    backup_count = 100

    file_name = 'zy'  # 对于轮换操作它还会设置文件名前缀。
    handler = logging.handlers.TimedRotatingFileHandler(filename=file_name, when=when_, backupCount=backup_count,
                                                        interval=interval_, encoding='utf-8')

    # 系统将通过为文件名添加扩展名来保存旧日志文件。扩展名是基于日期和时间的,根据轮换间隔的长短 使用strftime 格式%Y-%m-%d_%H-%M-%S 或是其中有变动的部分。


def test_3_a():
    # Formatter 类可以添加一个额外的可选 关键字参数style。它的默认值是'%',其他的值'{' 和'$' 也支持,对应了其他两种格式化样式。

    # 如果是使用{}-格式化(str.format()),你可以将{attrname} 用作格式字符串内的占位符。
    # 如果是使用$-格式化(string.Template),则会使用${attrname} 的形式。

    # _STYLES = {
    #     '%': (PercentStyle, BASIC_FORMAT),
    #     '{': (StrFormatStyle, '{levelname}:{name}:{message}'),
    #     '$': (StringTemplateStyle, '${levelname}:${name}:${message}'),
    # }

    root = logging.getLogger()
    root.setLevel(logging.DEBUG)

    handler = logging.StreamHandler()
    root.addHandler(handler)

    bf = logging.Formatter('{asctime} {name} {levelname:8s} {message}', style='{')
    handler.setFormatter(bf)

    root.debug('DEBUG日志')
    root.info('info日志')
    root.warning('warning日志')
    root.error('error日志')
    root.critical('critical日志')

    root.log(30, '')  # 30 是 WARNING

    # TODO 好奇怪 $asctime ${asctime} 都可以?
    df = logging.Formatter('$asctime--${name}--${levelname}--$message', style='$')
    handler.setFormatter(df)

    root.debug('DEBUG日志')
    root.info('info日志')
    root.warning('warning日志')
    root.error('error日志')
    root.critical('critical日志')

    root.critical('critical,%s', '--123--CRITICAL')

    # 任意对象都可用为日志信息的格式串,日志包将会调用该对象的str() 方法,以获取最终的格式串

    root.critical('critical,%s', 123)
    root.critical('critical,%s', 123.589)
    root.critical('critical,%s', [123.589, 78965.20])

创建Logger、Handler和Formatter,进行相关设置

"""
@blog: https://blog.csdn.net/zyooooxie
@qq: 153132336
"""

import logging
import logging.config
import time

abc = time.strftime('%Y%m%d_%H%M%S', time.localtime(time.time()))

def test_10_a1():
    # create logger
    logger = logging.getLogger('a1')
    logger.setLevel(logging.DEBUG)

    # create console handler and set level to INFO
    ch = logging.StreamHandler()
    ch.setLevel(logging.INFO)

    # create formatter
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    # add formatter to ch
    ch.setFormatter(formatter)
    # add ch to logger
    logger.addHandler(ch)

    logger.debug('debug message日志')
    logger.info('info message日志')
    logger.warning('warn message日志')
    logger.error('error message日志')
    logger.critical('critical message日志')


def test_10_a2():
    # 日志记录器是普通的Python 对象。addHandler() 方法对可以添加的日志处理器的数量没有限制。
    # 有时候,应用程序需要将所有严重性的所有消息记录到一个文本文件,而将错误或更高等级的消息输出到控制台。要进行这样的设定,只需配置适当的日志处理器即可

    # create logger
    logger = logging.getLogger('a2')
    logger.setLevel(logging.DEBUG)

    # create file handler which logs even debug messages
    fh = logging.FileHandler('10_a2.log')
    fh.setLevel(logging.DEBUG)

    # create console handler with a higher log level
    ch = logging.StreamHandler()
    ch.setLevel(logging.ERROR)

    # create formatter and add it to the handlers
    formatter = logging.Formatter('%(name)s - %(asctime)s -  %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    ch.setFormatter(formatter)

    # add the handlers to the logger
    logger.addHandler(fh)
    logger.addHandler(ch)

    logger.debug('debug message日志')
    logger.info('info message日志')
    logger.warning('warn message日志')
    logger.error('error message日志')
    logger.critical('critical message日志')

基于日志配置文件 进行配置,使用fileConfig()

[loggers]
keys=root,simpleExample

[logger_root]
level=DEBUG
handlers=consoleHandler,FileHandler,RH

[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0

[handlers]
keys=consoleHandler,FileHandler,RH

[handler_consoleHandler]
class=StreamHandler
level=INFO
formatter=simpleFormatter
args=(sys.stdout,)

[handler_FileHandler]
class=FileHandler
level=DEBUG
formatter=simpleFormatter
args=('10_b.log', 'w')

[handler_RH]
class=handlers.RotatingFileHandler
level=ERROR
# formatter=simpleFormatter
args=('10_b_RH.log', 'w', 5, 10)


[formatters]
keys=simpleFormatter

[formatter_simpleFormatter]
format= %(name)s - %(levelname)s - %(asctime)s - %(message)s
datefmt=%y-%m-%d %H:%M:%S

"""
@blog: https://blog.csdn.net/zyooooxie
@qq: 153132336
"""

def test_10_b():
    # 配置文件中的class指定类名时,该类名可以是相对于logging模块的相对值
    # 如下:
    # logging.StreamHandler
    # logging.FileHandler
    # logging.handlers.RotatingFileHandler

    logging.config.fileConfig('logging2.conf')

    # create logger
    logger = logging.getLogger()
    # logger = logging.getLogger('simpleExample')

    logger.debug('debug message日志')
    logger.info('info message日志')
    logger.warning('warn message日志')
    logger.error('error message日志')
    logger.critical('critical message日志')

    # fileConfig() 函数的参数:
    # fname:表示配置文件的文件名或文件对象
    # defaults:指定传给ConfigParser的默认值
    # disable_existing_loggers ,出于向后兼容的原因,默认为True 。这可能是你想要的,也可能不是你想要的,因为除非在配置中明确命名它们(或一个上级节点中),否则它将导致在fileConfig() 调用之前存在的任何非root 记录器被禁用。如果需要,请为此参数指定False 。


基于配置信息字典 进行配置,使用dictConfig()

"""
@blog: https://blog.csdn.net/zyooooxie
@qq: 153132336
"""

def test_10_c():

    log_dict = {
        'version': 1,
        'disable_existing_loggers': True,

        'formatters': {
            'simple': {'format': '%(levelname)s | %(asctime)s | %(message)s', 'datefmt': '%y-%m-%d %H:%M:%S'},
            'other': {'format': '%(asctime)s -- %(message)s'}},

        'handlers': {
            'console': {'level': 'ERROR', 'class': 'logging.StreamHandler', 'formatter': 'simple'},

            'file': {'level': 'INFO', 'class': 'logging.FileHandler', 'filename': '10_c.log',
                     'mode': 'w', 'encoding': 'utf-8', 'formatter': 'other'},

            'r_file': {'class': 'logging.handlers.RotatingFileHandler',
                       'filename': '10_c_{}.log'.format(abc),
                       'maxBytes': 10, 'backupCount': 2}},

        'loggers': {
            'simpleExample': {'level': 'DEBUG', 'handlers': ['console', 'file', 'r_file']}
        },

        'root': {'level': 'INFO', 'handlers': ['console', 'r_file']}

    }

    logging.config.dictConfig(log_dict)

    # create logger
    # logger = logging.getLogger()  # root
    logger = logging.getLogger('simpleExample')

    logger.debug('debug message日志')
    logger.info('info message日志')
    logger.warning('warn message日志')
    logger.error('error message日志')
    logger.critical('critical message日志')

本文链接:https://blog.csdn.net/zyooooxie/article/details/123635856

个人博客 https://blog.csdn.net/zyooooxie

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-12-25 11:04:55  更:2022-12-25 11:05:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/19 21:36:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码