一、日志基础知识

1、日志是什么

日志就像是软件程序的私人日记,它可以记录程序运行时发生的各种事件。开发人员可以在代码中调用日志记录的方法,来记录发生的事件。这些事件可以是一些重要的事情,我们称之为严重性级别(Level),并且可以附带一些描述性的消息和可变数据。

2、日志的作用

日志就像是软件程序的超级侦探,它可以帮助我们了解系统或软件程序的运行情况是否正常。当应用程序出现故障时,日志可以帮助我们快速定位问题。比如,开发者可以通过查看控制台上输出的各种日志来进行程序调试;而运维人员在接收到报警或问题反馈后,通常会先查看各种日志,因为大部分问题都可以在日志中找到答案。所以,日志的作用可以总结为以下三点:

  • 1、程序调试:日志就像是程序的调试助手,可以帮助开发人员找出问题所在。

  • 2、了解软件程序运行情况:通过记录和分析日志,我们可以了解软件程序的运行情况是否正常。

  • 3、软件程序运行故障分析与问题定位:当软件程序出现故障时,日志可以帮助我们快速定位问题,找出导致故障的原因。

3、日志的级别

日志的级别有很多,但我们一般只用四个,它们是日志级别的四大天王:DEBUG - INFO - WARN - ERROR

  • DEBUG(调试):就像是程序的调试小助手,可以帮助开发人员找出问题所在。但是在实际运行过程中,一般不会输出这个级别的日志,因为太多的DEBUG日志会让人眼花缭乱,就像是一本书上到处都是重点,失去了重点的意义。

  • INFO(通知):INFO日志级别主要用于记录系统运行状态等关联信息。这个级别的日志常用于向最终用户反馈系统当前状态,所以日志中的信息应该对最终用户有实际意义,让他们能够明白发生了什么事情。

  • WARN(警告):WARN日志常用于表示系统模块发生问题,但并不影响系统运行。当出现这个级别的日志时,我们可以进行一些修复性的工作,将系统恢复到正常状态。

  • ERROR(错误):当出现ERROR级别的日志时,意味着系统核心模块出现了问题,需要进行修复才能正常工作。虽然我们可以进行一些修复性的工作,但无法确定系统能否继续正常工作,因为这个问题可能导致系统在未来的某个阶段出现无法修复的错误,甚至宕机。

4、日志的内容

一条日志信息就像是一则新闻报道,需要包含以下内容:

  • 1、发生时间:就像是新闻报道中的时间戳,记录事件发生的具体时间。

  • 2、发生位置:就像是新闻报道中的地点,记录事件发生的具体位置。

  • 3、严重程度:就像是新闻报道中的重要性级别,记录事件的严重程度,也就是日志级别。

  • 4、内容:就像是新闻报道中的详细描述,记录事件的具体内容。

除了上述字段信息,一条日志记录还可能包含其他一些信息,比如进程ID、进程名称、线程ID、线程名称等。

日志格式就像是新闻报道的模板,定义了一条日志记录中包含哪些字段。而且,日志格式通常是可以自定义的,就像是可以根据新闻报道的需要来调整模板一样。

PS:当我们输出一条日志时,日志内容和日志级别是需要开发人员明确指定的。至于其他字段信息,只需要决定是否在日志中显示即可。

5、怎么使用日志

在Python中,有一个非常强大且易于使用的标准库模块logging,它就像是Python程序的日志管家。使用logging模块,我们可以轻松记录日志并进行灵活的配置。

希望这篇文章能帮助你更好地理解日志的概念和使用方法。记住,日志就像是软件程序的私人日记,它可以帮助我们了解程序的运行情况和定位问题。使用日志,让我们的程序更加健壮和可靠!

二、logging基础介绍

在部署项目的时候,我们可不能把所有的信息都直接扔到控制台上,那样可是会乱成一锅粥的!所以,我们可以把这些信息记录到日志文件里,这样不仅方便我们查看程序运行时的情况,还能像侦探一样根据日志快速定位问题的发生地点。就像是你在玩捉迷藏,日志文件就是你的线索,帮助你找到问题的藏身之处。

哎呀,别担心,我们有个好帮手,就是logging模块!它就像是你的私人秘书,会帮你记录下程序运行时的各种信息,比如错误、警告、调试信息等等。你只需要告诉它要记录什么级别的信息,它就会乖乖地把它们写进日志文件里,不会有丝毫怠慢。

想象一下,你在玩游戏,每次通过一个关卡,你都会有个小助手给你记下你的成绩和表现,logging模块就是你的游戏小助手,它会记录下你程序运行的点点滴滴,让你随时回顾和分析。

所以,小伙伴们,记得在你的Python项目中加入logging模块,让它成为你的得力助手,帮你解决问题,让你的程序运行如虎添翼!

import logging

1、logging库日志级别

问题思考:

  • 开发人员在开发一个应用程序时需要什么日志信息?在程序正式上线后需要什么日志信息?

开发人员就像是一位精密的手表制造师,他们需要详细的日志信息来监控程序的运行情况。就像手表制造师需要了解每个齿轮的运转是否顺畅,开发人员需要知道每个代码块的执行情况。因此,他们需要使用DEBUG级别的日志来追踪程序的每个细节,就像手表制造师需要观察每个齿轮的运动一样。

而当程序正式上线后,开发人员就像是将手表交给用户的销售员。他们不再需要了解每个代码块的执行情况,而是更关注整体的运行状态。就像销售员只需要知道手表是否正常运行,开发人员只需要使用INFO级别的日志来记录程序的重要信息,比如用户的请求和响应情况。

  • 运维人员在部署开发环境时需要什么日志信息?在部署生产环境时需要什么日志信息?

运维人员就像是一位机械师,他们负责将手表放入精心设计的展柜中,确保它在各种环境下都能正常运行。在部署开发环境时,运维人员需要使用WARNING级别的日志来记录一些警告信息,比如数据库连接失败或者配置文件错误。就像机械师需要检查手表的零件是否完好一样,运维人员需要确保开发环境的各个组件都能正常工作。

而在部署生产环境时,运维人员就像是将手表放入高档珠宝店的橱窗中,需要保证它的安全和稳定。他们需要使用ERRORCRITICAL级别的日志来记录程序的错误和严重问题,比如服务器崩溃或者数据库故障。就像珠宝店的橱窗需要保持完美无瑕一样,运维人员需要确保生产环境的稳定和安全。

根据需求选择不同的日志级别

在Python的日志处理中,就像选择一家餐厅的餐单一样,你需要根据你的需求挑选合适的日志级别:

级别

级别数值

使用时机

DEBUG

10 (级别最低)

供详细的、为了调试而生的信息。就像你在查找微小毛病时使用放大镜一样。

INFO

20(重要)

程序平稳运行时输出的一些基本信息。就像是一场顺风顺水的航海旅程中的风平浪静。

WARNING

30 (警告)

警告用户可能会发生问题,但程序依然能继续。就像是天气预报中的阵雨,提醒你带把伞。

ERROR

40(错误)

程序遇到严重问题,无法执行某些功能。就像是车辆发生了引擎故障,需要修理才能继续行驶。

CRITICAL

50 (严重)

程序遇到致命错误,无法继续运行。就像是船只遇到了海难,需要紧急撤离。

默认情况是日志级别是warning,日志级别从上到下依次升高,即 DEBUG < INFO < WARNING < ERROR < CRITICAL。而日志的信息量是依次减少的。

开发应用程序 或部署开发环境时:应该使用DEBUG 或INFO级别的日志获取尽可能详细的日志信息来进行开发或部署调试;

应用上线 或部署生产环境时:应该使用WARNING或CRITICAL级别的日志来降低机器的I/O压力和提高获取错误日志信息的效率

PS:当为某个应用程序指定一个日志级别后,应用程序会记录所有日志级别大于或等于指定日志级别的日志信息,而不是仅仅记录指定级别的日志信息,只要级别大于或等于该指定日志级别的日志记录才会被输出,小于该级别的日志记录将会被丢弃。

2、logging工作流程

在Python的写作舞台上,logging就像是一出精彩的戏剧,每个角色都扮演着不同的角色,共同完成一台完美的表演。

Logger:就像是这出戏的导演,它负责暴露函数给应用程序,决定哪些日志是值得记录的,就像是导演决定哪些场景是值得拍摄的。

LogRecord:是这出戏的演员,它接收导演的指示,将日志传递给相应的处理器进行处理,就像是演员将角色扮演得淋漓尽致。

Handler:是这出戏的舞台,它负责接收演员们的表演,将日志记录发送到合适的目的地,就像是舞台上的布景师将演员们的表演展示给观众。

Filter:是这出戏的剧本编辑,它提供了更好的粒度控制,决定哪些日志记录是值得输出的,就像是剧本编辑决定哪些情节是值得保留的。

Formatter:是这出戏的化妆师,它指定了最终输出中日志记录的布局,就像是化妆师为演员们打造出精美的妆容。

所以,logging工作流程就像是一台精心编排的戏剧,每个角色都扮演着重要的角色,共同创造出一场精彩的表演。

1719822139717.png

流程描述

  • 1、就像是在判断一场比赛的等级是否高于裁判的标准一样,如果高于,比赛继续,否则,直接判定结束比赛。

  • 2、产生日志就像是制作一道菜:第一步,检查是否有异常,有的话就加入异常调料。第二步,处理日志记录方法就像是烹饪中的调味过程,将各种食材搅拌均匀。

  • 3、使用注册到 Logger 对象中的 Filters 就像是在过滤咖啡时使用滤网一样。如果有多个过滤器,就像是多层滤网,只要有一层滤网不能通过,咖啡就不再继续过滤,处理流程也就此结束。否则,继续往下进行。

  • 4、在当前 Logger 对象中查找 Handlers,如果找不到任何 Handler,就像是在找不到炒菜的锅具一样,就往上找父 Logger 中的锅具。如果找到一个或多个 Handler,就像是找到了炒菜的锅具,依次用锅具来处理食材。但是在处理食材的过程中,会先判断食材的等级是否适合这个锅具,如果适合,就继续烹饪,否则,处理流程结束。

  • 5、执行 Handler 对象中的 filter 方法,就像是在烹饪时依次加入各种调料。如果有一个调料判断食材不合适,那么后面的调料就不再加入,直接将食材丢弃,处理流程结束。

  • 6、使用 Formatter 类格式化最终的输出结果,就像是在盘子上摆放美味的菜肴,不仅要好吃,还要看起来漂亮。注:Formatter 和之前的字符串格式化不同,它会添加额外的信息,就像是在盘子上加上装饰一样,让菜肴更有吸引力。

  • 7、真正地输出日志信息,就像是将菜肴端到餐桌上,无论是网络、文件、终端还是邮件,都是不同的餐具,由Handler的种类来决定。

3、日志输出格式

日志的输出格式可以认为设置,默认格式为下图所示:

1719822214956.png

4、基本使用

logging 就像是一个听话的小助手,使用起来简单得不得了。只需要调用 basicConfig() 方法,就能满足你的基本需求。如果你懒得传入参数,它会按照默认配置创建一个 Logger 对象。默认的日志级别被设置为 WARNING,就像是在提醒你小心哦。日志输出格式也是默认的,就像是穿上了一身整齐的制服。

这个小助手还有一些可选的参数,让你可以自定义它的表现。比如,你可以指定日志输出到文件的文件名,就像是给它找了一个家;还可以设置文件模式,就像是给它指定了一个行为规范;还可以定义日志输出的格式,就像是给它换了一身新衣服;还可以设置日志附带日期时间的格式,就像是给它戴上了一顶帽子;还可以设置格式占位符的风格,默认是 “%” 和 “{}”,就像是给它选择了一种口味。

另外,你还可以设置日志输出级别,就像是给它定了一个目标;定义输出流,用来初始化 StreamHandler 对象,但是不能和 filename 参数一起使用,否则会抛出 ValueError 异常,就像是给它指定了一个出口;还可以定义处理器,用来创建 Handler 对象,但是不能和 filename、stream 参数一起使用,否则也会抛出 ValueError 异常,就像是给它配备了一个助手。这个小助手真是个万能的小精灵啊!

参数名称

参数描述

filename

日志输出到文件的文件名

filemode

文件模式,r[+]、w[+]、a[+]

format

日志输出的格式

datefat

日志附带日期时间的格式

style

格式占位符,默认为 “%” 和 “{}”

level

设置日志输出级别

stream

定义输出流,用来初始化 StreamHandler 对象,不能 filename 参数一起使用,否则会ValueError 异常

handles

定义处理器,用来创建 Handler 对象,不能和 filename 、stream 参数一起使用,否则也会抛出 ValueError 异常

5、代码实战

指定日志输出级别

  • 默认日志级别输出

    import logging
    
    # 默认的日志输出级别为warning
    logging.debug('This is debug log')  # 调试级别
    logging.info('This is info log')  # 信息级别
    logging.warning('This is warning log')  # 警告级别
    logging.error('This is error log')  # 错误级别
    logging.critical('This is critical log')  # 严重错误级别

    输出结果如下:
    3.png

  • 使用baseconfig()来指定日志输出级别:

    import logging
    
    # 使用baseconfig()来指定日志输出级别
    logging.basicConfig(level=logging.DEBUG)
    
    logging.debug('This is debug log')  # 调试级别
    logging.info('This is info log')  # 信息级别
    logging.warning('This is warning log')  # 警告级别
    logging.error('This is error log')  # 错误级别
    logging.critical('This is critical log')  # 严重错误级别

    输出结果如下:
    4.png

输出日志到文件

import logging

# 使用baseconfig()来指定日志输出级别,日志信息写入test.log文件中
logging.basicConfig(filename="test.log", level=logging.DEBUG)  

logging.debug('This is debug log')  # 调试级别
logging.info('This is info log')  # 信息级别
logging.warning('This is warning log')  # 警告级别
logging.error('This is error log')  # 错误级别
logging.critical('This is critical log')  # 严重错误级别

生成文件test.log,文件内容如下:

5.png

注意:就好像每次打开冰箱都会有新的食物出现一样,如果想要每次执行程序都能够清空文件,然后再往里面写入日志,就像是每次打开一个新的空盒子一样,只需要在代码中加上filemode="w"这个属性,就像是在每次打开盒子之前先把里面的东西清空一样!

logging.basicConfig(filename="test.log",filemode="w",level=logging.DEBUG)

输出对象

import logging

logging.basicConfig(level=logging.DEBUG)
name = "张三"
age = "10"
logging.debug("姓名:%s, 年龄:%s", name, age)
logging.debug("姓名:%s, 年龄:%s" % (name, age))
logging.debug(("姓名 {},年龄 {}".format(name, age)))
logging.debug((f"姓名 {name},年龄 {age}"))

输出结果如下:
6.png

添加重要信息

  • asctime:就像是一位精准的时间管家,时刻准确地告诉你当前时间

  • levelname:就像是一位日志级别守护者,负责监控输出的重要程度

  • filename:就像是文件的身份证,能够准确地指出文件的名称

  • lineno:就像是文件的地址标签,告诉你报错的具体位置

  • message:就像是输出信息的传声筒,将重要信息传达给你

import logging

# 使用baseconfig()来指定日志输出级别,日志信息写入test.log文件中
# asctime:日期,levelname:级别,message:报错信息,filename:文件名,lineno:报错行数;datefmt:格式化时间字符串;level:修改默认日志级别
logging.basicConfig(filename="test.log", filemode="w",
                    format="%(asctime)s %(name)s:%(levelname)s:%(message)s|%(filename)s:%(lineno)s",
                    datefmt="%Y-%M-%d %H:%M:%S", level=logging.DEBUG)

logging.debug('This is a debug message')
logging.debug('This is debug log')  # 调试级别
logging.info('This is info log')  # 信息级别
logging.warning('This is warning log')  # 警告级别
logging.error('This is error log')  # 错误级别
logging.critical('This is critical log')  # 严重错误级别

生成文件test.log,文件内容如下:

7.png

三、logging高级应用

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

类名

说明

Loggers

记录器,提供应用程序代码能直接使用的接口。

Handlers

处理器,将记录器产生的日志发送至目的地

Filters

过滤器,提供更好的粒度控制,决定那些日志会被输出

Formatters

格式化器,设置日志内容的组成结构和消息字段

logging模块的工作流程:
8.png

1、loggers记录器

  • 1、提供应用程序的调用接口(logger是单例的)

    logger  = logging.getLogger(__name__)
  • 2、决定日志记录的级别

    logger.setLevel()
  • 3、将日志内容传递相关联的handlers中

     logger.addHandler()和logger.removeHandler()

2、Handlers处理器

它们就像快递员一样,负责将日志送到不同的目的地:文件、标准输出、邮件,甚至可以通过socke、http等协议送到任何地方。

  • SreamHandler:就像是快递小哥,负责把日志送到标准输出stdout(就是显示器啦)。

    创建方法:sh = logging.StreamHandler(stream=None)

  • FileHandle:这个处理器就像是快递小哥把日志送到磁盘文件。

    创建方法:fh=logging.FileHandler(filename,mode=“a”,encoding=Node,delay=False)

    setFormatter():就像给快递小哥指定了送货的衣服一样,设置当前handler对象使用的消息格式。

    9.png

3、Formatters 格式

Formatter对象就像是搭积木一样,可以帮助我们最终搭建出完美的日志信息结构。

构造方法:想象一下,就好像是在搭建乐高积木一样,使用ft = logging.Formatter.__init__(fmt=None,datefmt=None,style='%')这个方法来开始我们的构建。

datefmt默认格式为:时间格式默认是%Y-%m-%d %H:%M:%S,就像是在设置一台时间机器,让我们可以准确地回到过去或者未来一样;而style参数默认为百分符%,这就好比是在使用魔法符号%(<dictionary key>)s,让我们可以从字典中取出我们需要的信息。

属性

格式

描述

asctime

%(asctime)s

日志产生时间,默认格式为 2021-11-23 10:20:30,123

created

%(created)f

time.time()生成的日志创建时间戳

filename

%(filename)s

生成日志的程序名

funcName

%(funcName)s

调用日志的函数名

levelname

%(levelname)s

日志级别(DEGBU、INFO、WARNING、ERROR、CRITICAL)

levelno

%(levelno)s

日志级别对应的数值

lineno

%(lineno)d

日志所针对的代码行号(报错代码所在行数)

module

%(module)s

生成日志的模块名

msecs

%(msecs)d

日志生成时间的毫秒部分

message

%(message)s

具体的日志信息

name

%(name)s

日志调用者

pathname

%(pathname)s

生成日志的完整路径

processName

%(processName)s

进程名(如果可用)

thread

%(thread)d

生成日志的线程id(如果可用)

process

%(process)d

生成日志的进程id

threadName

%(threadName)s

线程名(如果可用)

四、高级用法实战

1、记录器

  • 默认情况:

    import logging
    
    logger = logging.getLogger()
    print(logger)
    print(type(logger))

    输出结果如下:
    10.png

  • 修改为指定级别

    import logging
    
    logger = logging.getLogger("applog")  # 修改的显示名称
    logger.setLevel(logging.DEBUG)  # 修改日志级别
    print(logger)
    print(type(logger))

    输出结果如下:
    11.png

2、处理器

  • 普通处理器定义

    consoleHandler = logging.StreamHandler()
    consoleHandler.setLevel(logging.DEBUG)
  • 写入文件处理器定义

    # 写入文件,没有给handler指定日志级别,将使用logger的级别
    fileHandler = logging.FileHandler(filename="test.log")
    fileHandler.setLevel(logging.INFO)
  • 设置formatter格式

    # 给处理器设置formatter格式
    formatter = logging.Formatter("%(asctime)s %(name)s:%(levelname)s:%(message)s|%(filename)s:%(lineno)s")
  • 处理器设置格式

    # 给处理器设置格式
    consoleHandler.setFormatter(formatter)
    fileHandler.setFormatter(formatter)
  • 记录器要设置处理器

    logger.addHandler(consoleHandler)
    logger.addHandler(fileHandler)

完整代码:

import logging

# 记录器
logger = logging.getLogger("applog")  # 修改的显示名称
logger.setLevel(logging.DEBUG)  # 修改日志级别

# 处理器
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.DEBUG)

# 写入文件,没有给handler指定日志级别,将使用logger的级别
fileHandler = logging.FileHandler(filename="test.log")
fileHandler.setLevel(logging.INFO)

# 给处理器设置formatter格式; 8s:表示s前面的占8位;-8s:左对齐
formatter = logging.Formatter("%(asctime)s %(name)s:%(levelname)8s:%(message)s|%(filename)s:%(lineno)s")

# 给处理器设置格式
consoleHandler.setFormatter(formatter)
fileHandler.setFormatter(formatter)

# 记录器要设置处理器
logger.addHandler(consoleHandler)
logger.addHandler(fileHandler)

# 打印日志的代码
logger.debug('This is debug log')  # 调试级别
logger.info('This is info log')  # 信息级别
logger.warning('This is warning log')  # 警告级别
logger.error('This is error log')  # 错误级别
logger.critical('This is critical log')  # 严重错误级别

输出结果:

  • 控制台
    12.png

  • test.log文件中
    13.png

3、过滤器

#定义过滤器;过滤开头名称为cn.cccb的文件
fit = logging.Filter("cn.cccb")
#关联过滤器
logger.addFilter(fit)

输出结果

  • 控制台无数据
    14.png

  • test.log文件中无数据
    13.png

想要正常显示,需要修改记录器的自定义名称

logger = logging.getLogger("cn.cccb.log")

输出结果如下

  • 控制台
    16.png

  • test.log文件
    17.png

当然我们在设置过滤器的时候,我们也可以指定给我们的某个handler处理器指定过滤器来过滤,我们修改代码完整如下:

import logging

# 记录器
logger = logging.getLogger("apploglog")  # 修改的显示名称
logger.setLevel(logging.DEBUG)  # 修改日志级别

# 处理器
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.DEBUG)

# 写入文件,没有给handler指定日志级别,将使用logger的级别
fileHandler = logging.FileHandler(filename="test.log")
fileHandler.setLevel(logging.INFO)

# 给处理器设置formatter格式; 8s:表示s前面的占8位
formatter = logging.Formatter("%(asctime)s %(name)s:%(levelname)8s:%(message)s|%(filename)s:%(lineno)s")

# 给处理器设置格式
consoleHandler.setFormatter(formatter)
fileHandler.setFormatter(formatter)

# 记录器要设置处理器
logger.addHandler(consoleHandler)
logger.addHandler(fileHandler)

# 定义过滤器;过滤开头名称为cn.cccb的文件
fit = logging.Filter("cn.cccb")

# 关联过滤器
# logger.addFilter(fit)
fileHandler.addFilter(fit)

# 打印日志的代码
logger.debug('This is debug log')  # 调试级别
logger.info('This is info log')  # 信息级别
logger.warning('This is warning log')  # 警告级别
logger.error('This is error log')  # 错误级别
logger.critical('This is critical log')  # 严重错误级别

输出结果
18.png
19.png
以上的一些方式,在我们日常使用的简单过程中,我们这样定义就可以了,但是如果我们在大型的项目过程中,如果去定义的话,那么我们就不能这样去做,我们总不能修改个日志等级的话,我们都需要去修改下代码吧?

于是我们采用了和java中日志记录相关的方式,我们将这些配置记录在我们的配置文件中,这样就很方便我们去进行修改了。

4、配置文件定义

新建一个logging.conf文件,新增如下内容(复制代码进去):

[loggers]
keys=root,applog

[handlers]
keys=fileHandler,consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_applog]
level=DEBUG
handlers=fileHandler,consoleHandler
qualname=applog
propagate=0


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

[handler_fileHandler]
class=handlers.TimedRotatingFileHandler
args=("applog.log","midnight",1,0)
level=DEBUG
formatter = simpleFormatter

[formatter_simpleFormatter]
format=%(asctime)s|%(levelname)8s|%(name)s:%(lineno)s|%(message)s|%(processName)s
datafm=%Y-%m-%d %H:%M:%S

代码解读

  • [loggers][handlers][formatters]:就像是搭建一个日志大厦,分别定义了记录器、处理器和格式化器,每个部分都有自己的功能和作用。

  • [logger_root]:就好像是为大厦的根基进行了属性设置,确保整个大厦的稳固。

  • [logger_applog]:就像是为一个特定的房间进行了属性设置,指定了处理器对象,而qualname=applog就像是给这个房间设置了一个特殊的门,只有通过特定的方式才能进入。

  • [handler_consoleHandler]:就像是定义了一个可以输出到控制台的处理器对象,就好像是一个管道,将信息传送到控制台。

  • [handler_fileHandler]:就像是定义了一个按时间滚动生成文件的处理器对象,就好像是一个定时备份的机器,每天凌晨12点准时备份数据。

  • [formatter_simpleFormatter]:就像是定义了一个输出内容格式的格式化器,就好像是给信息添加了一个精美的外衣,让输出更加整洁。

5、代码异常记录日志

import logging.config

# 使用配置文件的方式来处理日志
logging.config.fileConfig('logging.conf')

rootLogger = logging.getLogger()
rootLogger.debug("This is root Logger, debug")

# 记录器
logger = logging.getLogger("applog")  # 修改的显示名称
# 打印日志的代码
logger.debug('This is debug log,bug')  # 调试级别

# 设置报错将str转换成int

输出结果(此时我们直接转换会出错,但是在我们的日志文件并不打印):
20.png

21.png

使用try...catch捕捉异常处理就可以输入到日志文件中:

a = "abc"
try:
    int(a)
except Exception as e:
    logger.exception(e)

输出结果:
22.png
23.png

我们发现不仅是在控制台上,在文件中也进行了具体的输出。此时我们全部讲完了logging标准库。