1、日志级别2、logging流程3、几个重要的类3.1 Logger类3.1.1 最经常使用的配置方法3.1.2 建立Logger对象logging.getLogger([name])3.2 Handler类3.3 Filter类3.4 Formatter类4、使用示例4.1 直接调用logging接口4.2 使用basicConfig()函数4.3 一步步配置Logger4.4 经过dictConfig配置4.4.1 dictConfig()4.4.2 配置规则4.4.3 配置示例html
开发部署项目时,不可能将全部的信息都输出到控制台中,所以咱们将这些信息记录到日志文件中,不只方便查看程序运行的状况,也能够在项目出现故障时根据该运行时产生的日志快速定位问题。python
Python
中提供了日志模块logging
,能够方便的记录日志信息。web
本文主要分析了
logging
模块的相关知识及具体使用。
当前介绍该日志模块的文章有不少,之因此还要进行记录,一方面是由于没有看到系统的介绍,二是经过梳理此部份内容,作到不止会用,还明白内部函数调用。服务器
Python
标准库logging
用作记录日志,默认分为五种日志级别:网络
DEBUG(10)
:详细信息,调试问题时所需INFO(20)
:证实事情可按预期工做WARNING(30)
:有意外,未来可能发生问题,但依然可用ERROR(40)
:严重问题,程序不能执行一些功能CRITICAL(50)
:严重错误咱们自定义日志级别时注意不要和默认的日志级别数值型相同(这是什么意思呢?),logging
执行时输出大于等于设置的值日级别的日志信息,如设置级别为INFO,则INFO, WARNING, ERROR, CRITICAL级别的日志都会输出。
5种等级分别对应5种日志打印方法:debug, info, warning, error, critical
。
默认的是WARNING
,即当等级大于等于WARNING
才被跟踪。app
官方的logging
模块工做流程图以下:
函数
从上图中能够看到这几种python类型,Logger, LogRecord, Filter, Handler, Formatter
。
类型说明布局
Logger
:日志,暴露函数给应用程序,基于日志记录器和过滤器级别决定哪些日志有效。LogRecord
:日志记录器,将日志传到相应的处理器处理。Handler
:处理器,将(日志记录器产生的)日志记录发送至合适的目的地。Filter
:过滤器,提供了更好的粒度控制,它能够决定输出哪些日志记录。Formatter
:格式化器,指明了最终输出中日志记录的布局。 基本流程:学习
Logger
对象对于设置的级别是否可用,若是可用,则往下执行,不然,流程结束。LogRecord
对象,若是注册到Logger
对象中的Filter
对象过滤后返回False, 则不记录日志,流程结束,不然,向下执行。LogRecord
对象将Handler
对象传入当前的Logger
对象,(图中子流程)若是Handler
对象的日志级别大于设置的日记级别,再判断注册到Handler
对象中的Filter
对象过滤后是否返回True而放行输出日志信息,不然不放行,流程结束。Handler
大于Logger
中设置的级别,也即Handler
有效,则往下执行,不然,流程结束。Logger
对象是否还有父Logger
对象,若是没有(表明当前Logger
对象是最顶层的Logger
对象root Logger
),流程结束。不然将Logger
对象设置为它的父Logger
对象,重复上面3,4两步,输出父类Logger
对象中的日志输出,直到是root Logger
对象。前面讲logging
流程的时候,提到几个概念:Logger
,Handler
,Filter
,Formatter
。ui
Logger
对象有3个任务要作:
info, debug
等方法,使应用程序能够在运行时记录日志消息Filter
对象来决定要对哪些日志进行后续处理handlers
一个系统只有一个根Logger
对象,而且该对象不能被直接实例化。
经过调用
logging.getLogger(name)
函数建立Logger
类对象。
Logger
对象最经常使用的方法有两类:(1)配置方法,(2)消息发送方法
Logger
对象能够设置多个Handler
对象和Filter
对象,Handler
对象能够设置Formatter
对象。Formatter
对象用来设置消息的具体输出格式。
方法 | 描述 |
---|---|
Logger.setLevel |
设置日志器将会处理的日志消息的最低严重级别 |
Logger.addHandler() |
为该Logger 对象添加一个handler 对象 |
Logger.removeHandler |
为该Logger 对象移除一个handler 对象 |
Logger.addFilter()和Logger.removeFilter() |
为该Logger 对象添加 和 移除一个filter 对象 |
logger
对象配置完成后,可以使用下面的方法来建立日志记录:
Logger.debug(), Logger.info(), Logger.warning(), Logger.error(), Logger.critical()
:建立一个与他们的方法名对应等级的日志记录Logger.exception()
:建立一个相似于Logger.error()
的日志消息Logger.log()
:须要获取一个明确的日志level参数来建立一个日志记录1. 获取Logger
对象
一般是经过--logging.getLogger()
的方法。该方法有一个可选参数name
,该参数表示将要返回的日志器的名称标识,若是不提供该参数,则其值为root
。
若以相同的name
参数值屡次调用getLogger()
方法,将会返回指向同一个Logger
对象的引用。
2. logger的层级结构与有效等级
logger
的名称是一个以 '.'
分割的层级结构,每一个'.'
后面的logger
都是'.'
前面的logger
的children
,例如,有一个名称为 foo
的logger
,其它名称分别为foo.bar, foo.bar.baz
和 foo.bam
都是 foo
的后代。
logger
有一个"有效等级(effective level
)"的概念。若是一个logger上没有被明确设置一个level,那么该logger就是使用它parent的level;若是它的parent
也没有明确设置level
则继续向上查找parent
的parent
的有效level
,依次类推,直到找到个一个明确设置了level
的祖先为止。须要说明的是,root logger
老是会有一个明确的level
设置(默认为 WARNING
)。当决定是否去处理一个已发生的事件时,logger
的有效等级将会被用来决定是否将该事件传递给该logger
的handlers
进行处理。
child loggers
在完成对日志消息的处理后,默认会将日志消息传递给与它们的祖先loggers
相关的handlers
。所以,咱们没必要为一个应用程序中所使用的全部loggers定义和配置handlers,只须要为一个顶层的`logger`配置`handlers`,而后按照须要建立child loggers
就可足够了。咱们也能够经过将一个logger的propagate
属性设置为False来关闭这种传递机制。
日志记录的工做主要由Logger
对象来完成。前面讲到一个系统只有一个根Logger
对象,而且该对象不能被直接实例化。
须要经过logging.getLogger([name])
来获取Logger
对象。
在调用getLogger
时要提供Logger
的名称(屡次使用相同名称来调用getLogger,返回的是同一个对象的引用。),Logger
实例之间有层次关系,这些关系经过Logger
名称来体现。
1p = logging.getLogger(“root”)
2c1 = logging.getLogger(“root.c1”)
3c2 = logging.getLogger(“root.c2”)
复制代码
例子中,p
是父logger
, c1,c2
分别是p的子logger
。c1, c2
将继承p
的设置。若是省略了name
参数, getLogger
将返回日志对象层次关系中的根Logger
。
每一个Logger
对象均可以设置一个名字,若是设置logger = logging.getLogger(__name__)
,__name__
是Python
中的一个特殊内置变量,他表明当前模块的名称(默认为__main__
)。
该函数内部根据是否指定名称返回对应的Logger对象。
1root = RootLogger(WARNING)
2Logger.root = root
3Logger.manager = Manager(Logger.root)
4
5def getLogger(name=None):
6 """
7 Return a logger with the specified name, creating it if necessary.
8 If no name is specified, return the root logger.
9 """
10 if name:
11 return Logger.manager.getLogger(name)
12 else:
13 return root
复制代码
示例:
1import logging
2logger = logging.getLogger('test')
3logger.warning('this is a warning info')
4# 输出
5WARNING:test:this is a warning info
复制代码
Handler
对象的做用是(基于日志消息的等级)将消息分发到handler
指定的位置(文件、网络、邮件等)。Logger
对象能够经过addHandler()
方法为本身添加handler
对象。
应用程序代码不该该直接实例化和使用
Handler
实例。由于Handler
是一个基类,只定义了全部handlers
都应该有的接口,同时提供了一些子类能够直接使用或覆盖的默认行为。经常使用接口有:
setLevel()
setFormatter()
set_name()
经常使用的Handler
:
Handler | 描述 |
---|---|
logging.StreamHandler |
将日志消息发送到输出到Stream ,如std.out, std.err 或任何file-like 对象。 |
logging.FileHandler |
将日志消息发送到磁盘文件,默认状况下文件大小会无限增加 |
logging.handlers.RotatingFileHandler |
将日志消息发送到磁盘文件,并支持日志文件按大小切割 |
logging.hanlders.TimedRotatingFileHandler |
将日志消息发送到磁盘文件,并支持日志文件按时间切割 |
logging.handlers.HTTPHandler |
将日志消息以GET 或POST 的方式发送给一个HTTP 服务器 |
logging.handlers.SMTPHandler |
将日志消息发送给一个指定的email地址 |
logging.NullHandler |
该Handler 实例会忽略error messages ,一般被想使用logging 的library 开发者使用来避免'No handlers could be found for logger XXX' 信息的出现。 |
类之间的继承关系以下:
示例:
1import logging
2
3logger = logging.getLogging() # 获取Logger对象
4handler = logging.FileHandler('output.log', mode='a', encoding=None, delay=False)
5formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s',
6 datefmt='%Y-%m-%d %H:%M:%S',
7 style='%')
8handler.setFormatter(formatter) # handler对象设置格式
9handler.setLevel(logging.DEBUG)# handler设置日志级别
10
11logger.addHandler(handler) # 添加handler对象
复制代码
Filter
实例用于执行日志记录的任意筛选。Loggers
和Handlers
能够根据须要使用筛选器实例筛选记录.logging
标准库只提供了一个base filter
,其构造函数__init__
接收name
,默认的行为是名为name
的logger
及其子logger
的消息能经过过滤器,其他的被过滤掉。
1class Filter(object):
2 """
3 Filter instances are used to perform arbitrary filtering of LogRecords.
4 """
5 def __init__(self, name=''):
6 """
7 Initialize a filter.
8
9 Initialize with the name of the logger which, together with its
10 children, will have its events allowed through the filter. If no
11 name is specified, allow every event.
12 """
13 self.name = name
14 self.nlen = len(name)
复制代码
Formatter
对象用于配置日志信息的最终顺序、结构和内容。与logging.Handler
基类不一样的是,应用代码能够直接实例化Formatter
类。
Formatter
类的构造方法定义以下:logging.Formatter.__init__(fmt=None, datefmt=None, style='%')
该方法可接收3个可选参数:
fmt
:指定消息格式化字符串,若是不指定该参数则默认使用message
的原始值datefmt
:指定日期格式字符串,若是不指定,则默认使用"%Y-%m-%d %H:%M:%S"
style
:可取值为'%', '{'和'$'
,若是不指定,则默认使用'%'
格式 | 含义 |
---|---|
%(levelno)s |
打印日志级别的数值 |
%(levelname)s |
打印日志级别名称 |
%(pathname)s |
打印当前执行程序的路径 |
%(filename)s |
打印当前执行程序名 |
%(funcName)s |
打印日志的当前函数 |
%(lineno)d |
打印日志的当前行号 |
%(asctime)s |
打印日志的时间 |
%(thread)d |
打印线程ID |
%(message)s |
打印日志信息 |
%(process)s |
当前进程,进程ID |
%(module)s |
调用日志输出函数的模块名,filename 的名称部分,不包含后缀 |
%(msecs)d |
日志事件发生事件的毫秒部分。logging.basicConfig() 中用参数datefmt 将会去掉asctime 中产生的毫秒部分,能够用这个加上。 |
通常直接使用logging.Formatter(fmt, datefmt)
1import logging
2fmt = "%(asctime)s [%(filename)s:%(lineno)d] %(levelname)s: %(message)s"
3datefmt="%Y-%m-%d %H:%M:%S"
4logFormatter = logging.Formatter(fmt, datefmt)
复制代码
该部分主要展现如何使用
logging
模块记录日志信息的使用方法。
默认的输出格式以下:
logging
模块如何使用呢?下面介绍几种经常使用的使用方式:
一是使用logging
的对外函数接口;二是使用basicConfig()
方法,该方法可以知足基本的使用需求;三是经过建立Logger
对象,能够进行更加复杂的处理。
最简单的使用方法,就是直接调用logging
标准库的接口,如logging.debug()
,logging.info()
等函数。
默认的日志级别是WARNING
,当等级大于等于WARNING
才被跟踪。
内部默认调用的是
root.log(level, mas)
函数
接口函数以下:
debug()
info()
warning()
error()
critical()
也能够直接使用同一接口logging.log()
,输入级别及具体信息。
log(level, msg)
:level
表示日志级别,输入日志级别对应的整数或代码,以下:1 CRITICAL = 50
2 FATAL = CRITICAL
3 ERROR = 40
4 WARNING = 30
5 WARN = WARNING
6 INFO = 20
7 DEBUG = 10
8 NOTSET = 0
复制代码
这些接口函数内部实际调用的都是Logger
类的对应函数。若是logger
没有handler
时,可默认调用basicConfig()
添加控制台handler
。
如,logging.info()
函数内部调用root.info()
函数,以下
1def info(msg, *args, **kwargs):
2 """
3 Log a message with severity 'INFO' on the root logger. If the logger has
4 no handlers, call basicConfig() to add a console handler with a pre-defined
5 format.
6 """
7 if len(root.handlers) == 0:
8 basicConfig()
9 root.info(msg, *args, **kwargs)
复制代码
示例以下:
1import logging
2logging.warning('this is a warning info.')
3logging.error('this is a error info.')
4logging.debug('this is a debuginfo.')
5# 输出
6WARNING:root:this is a warning info.
7ERROR:root:this is a error info.
8
9logging.log(20, 'this is a info msg.')
10logging.log(30, 'this is a warn msg.')
11# 输出:
12WARNING:root:this is a warn msg.
复制代码
记录具体异常信息
当发生异常时,直接使用无参数的debug(), info(), warning(), error(), critical()
方法并不能记录异常信息。
咱们看一下各个接口的定义及参数:
1# 普通接口
2def warning(msg, *args, **kwargs)
3# 内部调用以下函数:
4self._log(WARNING, msg, args, **kwargs)
5
6# 统一接口
7def log(level, msg, *args, **kwargs)
8# 内部调用以下函数:
9self._log(level, msg, args, **kwargs)
10
11# exception函数,参数中默认exc_info为True
12def exception(msg, *args, exc_info=True, **kwargs):
13 error(msg, *args, exc_info=exc_info, **kwargs)
14# 内部调用以下函数:
15self._log(ERROR, msg, args, **kwargs)
复制代码
由上面代码可见,其内部都是调用函数Logger._log(level, msg, args, **kwargs)
。不一样的是参数,如level
日志级别。
函数Logger._log()
的定义以下:
1def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False)
2
复制代码
可见,其除了level
, msg
之外,还有参数exc_info
。该参数用来控制是否打印具体信息。
函数exception()
就等于error(msg, exc_info=True)
所以:
记录异常信息的方法:
exc_info
参数为True
,指示是否打印执行信息exception()
方法,同时记录当前的堆栈追踪(仅从异常处理程度调用此方法)log()
方法,可是要设置日志级别和exce_info
参数。logger.log(level, msg, exc_info=True)
是各个接口函数的统一调用方式。
示例代码:
1import logging
2
3logging.basicConfig(filename="test.log", filemode="w", format="%(asctime)s %(name)s:%(levelname)s:%(message)s", datefmt="%d-%M-%Y %H:%M:%S", level=logging.DEBUG)
4a = 5
5b = 0
6try:
7 c = a / b
8except Exception as e:
9 # 下面三种方式三选一,推荐使用第一种
10 logging.exception("Exception occurred")
11 logging.error("Exception occurred", exc_info=True)
12 logging.log(level=logging.DEBUG, msg="Exception occurred", exc_info=True)
复制代码
输出文件test.log
的内容:
使用basicConfig()
方法就可以知足基本的使用须要,若是方法没有传入参数,会根据默认的配置建立Logger
对象,默认的日志级别被设置为WARNING。
默认的日志输出格式:
WARNING | root | message |
---|---|---|
日志级别 | Logger 实例 |
日志信息 |
函数定义:def basicConfig(**kwargs)
该函数可选的参数以下表所示:
参数名称 | 参数描述 |
---|---|
filename |
日志输出到文件的文件名 |
filemode |
文件模式,r[+] 、w[+] 、a[+] |
format |
日志输出的格式 |
datefmt |
日志附带日期时间的格式 |
style |
格式占位符,默认为“%” 和“{}” |
level |
设置日志输出级别 |
stream |
定义输出流,用来初始化 StreamHandler 对象,不能和 filename 参数一块儿使用,不然会ValueError 异常 |
handles |
定义处理器,用来建立Handler 对象,不能和filename,stream 参数一块儿使用,不然也会抛出ValueError 异常 |
stream
输出流不与filename
输出文件一块儿使用handler
处理器不与stream
输出流或filename
输出文件一块儿用- 即
stream
、filename
和handler
互相排斥- 若想将日志信息同时输出到文件和控制台,则须要使用
Logger
处理器增长对应的处理方法。
basicConfig()
方法能够实现将日志信息输出到文件中或者输出到定义的输出流中。
filename
参数,或者经过handler
处理器建立相应文件对象实现
其中,format
指定输出的格式和内容,format
能够输出不少有用信息,具体格式见Formatter类
。
该方法至关于显示调用basicConfig()
进行参数的配置,而直接调用logging.info()
接口函数,若没有handler
时,是隐式调用basicConfig()
的默认参数形式。
1)日志信息打印到输出流
1import logging
2# 直接调用basicConfig()函数,使用默认参数
3logging.basicConfig()
4logging.debug('This is a debug message')
5logging.info('This is an info message')
6logging.warning('This is a warning message')
7logging.error('This is an error message')
8logging.critical('This is a critical message')
9
10# 输出:(默认级别是WARNING)
11WARNING:root:This is a warning message
12ERROR:root:This is an error message
13CRITICAL:root:This is a critical message
复制代码
2)格式化输出
格式化输出时间:
经过datefmt
参数能够格式化输出log
的时间。
经常使用的输出格式以下:format = '%(asctime)s - %(filename)s[line:%(lineno)d]- %(levelname)s: %(message)s'
该格式能够输出日志的打印时间,输出模块及行号,日志级别和输出的日志内容。
1import logging
2logging.basicConfig(format='%(asctime)s %(message)s', datefmt = '%Y-%m-%d %I:%M:%S %p')
3logging.warning('is when this event was occurred.')
4
5# 输出结果
62019-10-15 04:03:17 PM is when this event was occurred.
复制代码
3) 将日志输出到指定文件
指定filename
, filemode
参数,可将日志内容输出到指定文件,示例代码以下:
1import logging
2
3logging.basicConfig(filename='test.log', filemode='w', format="%(asctime)s %(name)s:%(levelname)s:%(message)s", datefmt="%d-%M-%Y %H:%M:%S", level=logging.DEBUG)
4logging.debug('This is a debug message')
5logging.info('This is an info message')
6logging.warning('This is a warning message')
7logging.error('This is an error message')
复制代码
生成的日志文件test.log
,内容以下:
basicConfig
函数提供了一种较为简便的使用日志的方式,若是想要获取更加复杂的使用,则须要本身一步步配置来实现。
配置逻辑:
logger
对象能够添加多个handler
对象,经过addHandler()
函数handler
对象能够有一个Formatter
对象来指定格式,经过setFormatter()
函数handler
和logger
对象都须要设置一个日志等级,经过setLevel()
函数logger
和handler
对象能够添加多个Filter
对象,经过addFilter()
函数示例:
1import logging
2
3logger = logging.getLogger(__name__)
4logger.setLevel(level=logging.INFO)
5
6handler = logging.FileHandler('output.log', mode='a', encoding=None, delay=False)
7formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s',
8 datefmt='%Y-%m-%d %H:%M:%S',
9 style='%')
10handler.setFormatter(formatter)
11handler.setLevel(logging.DEBUG)
12handler.set_name('output-log')
13
14logger.addHandler(handler)
15
16a=0
17try:
18 res = 100 / a
19except:
20 logger.error('Divisor is equal to 0.', exc_info=True)
复制代码
将日志同时输出到屏幕和文件
1import logging
2logger = logging.getLogger(__name__)
3logger.setLevel(level = logging.DEBUG)
4handler = logging.FileHandler("log.txt")
5handler.setLevel(logging.INFO)
6formatter = logging.Formatter('%(asctime)s - %(name)s - %(message)s')
7handler.setFormatter(formatter)
8
9console = logging.StreamHandler()
10console.setLevel(logging.INFO)
11
12logger.addHandler(handler)
13logger.addHandler(console)
14
15logger.info("Start print log")
16logger.debug("Do something")
17logger.warning("Something maybe fail.")
18logger.info("Finish")
复制代码
在log.txt
文件和控制台都可看到输出,控制台的输出,其中文件中内容(有格式)以下:
logging
有一个日志处理的主对象(
logger=logging.getLogger()
),其余的处理方法均是经过
addHandler
添加进去。
经过dictConfig
配置方法是经过python代码构建一个dict
对象,也能够经过JSON
或yaml
文件来进行配置。
这种方式使用起来更加灵活,强大。咱们能够把不少的数据转换成自字典形式,而后将他们填充到一个配置字典中。
具体如何转换能够参考logging.config.py
文件。
该函数能够从一个字典对象中获取日志配置信息,config
参数就是这个字典对象。
定义以下:
1def dictConfig(config):
2 """Configure logging using a dictionary."""
3 dictConfigClass(config).configure()
复制代码
如使用YAML
格式的文件类配置(配置内容见下方示例),则使用示例:
1import logging
2import logging.config
3import yaml
4
5with open('logging.yml', 'r') as f_config:
6 dict_cfg = yaml.load(f_config)
7logging.config.dictConfig(dict_cfg)
8
9logger = logging.getLogger('console')
10logger.debug('debug msg')
复制代码
key名称 | 描述 |
---|---|
version |
必选项,整数值,表示配置格式版本,当前惟一可用值是1 |
formatters |
可选项,其值是字典对象,该字典对象每一个元素的key 为要定义的格式器名称,value 为格式器的配置信息组成的dict 。通常会配置format ,用于指定输出字符串的格式,datefmt 用于指定输出的时间字符串格式,默认为%Y-%m-%d %H:%M:%S 。 |
filters |
可选项,其值是字典对象,该字典对象每一个元素的key 为要定义的过滤器名称,value 为过滤器的配置信息组成的dict 。 |
handlers |
可选项,其值是字典对象,该字典对象每一个元素的key 为要定义的处理器名称,value 为处理器的配置信息组成的dict 。如class (必选项), formatter , filters 。其余配置信息将会传递给class 所指定的处理器类的构造函数。如使用logging.handlers.RotatingFileHandler ,使用maxBytes , backupCount 等参数。 |
loggers |
可选项,其值是字典对象,该字典对象每一个元素的key 为要定义的日志器名称,value 为日志器的配置信息组成的dict 。如level, handler, filter 等 |
root |
可选项,这是root logger 的配置项,其值是字典对象。除非在定义其它logger 时明确指定propagate 值为no,不然root logger 定义的handlers 都会被做用到其它logger 上。 |
incremental |
可选项,默认值为False 。该选项的意义在于,若是这里定义的对象已经存在,那么这里对这些对象的定义是否应用到已存在的对象上。值为False 表示,已存在的对象将会被从新定义。 |
具体配置结构以下所示:
version
: 必要参数,必须为1
incremental
:是否将此配置文件解释为现有配置的增量, 默认为False
disable_existing_loggers
:是否要禁用现有的非 root logger
,默认为True
handlers
:字典形式
class
:必须有,所使用的handler
类,如logging.handlers.RotatingFileHandler
level
:(可选),handler
的等级formatter
:(可选),当前handler
的formatter
的id
filters
:(可选),当前handler
的filters
的id
列表loggers
:字典形式
level
:(可选),logger
的等级propagate
:(可选):默认值为1,表示将消息传递给父logger
的handler
进行处理。filters
:(可选)handlers
:(可选) ,当前logger
的handlers
的id
列表qualname
:代码中使用logging.getLogger()
时,读取的就是qualname
这个选项。root
:这是root logger
的配置项
level
:日志等级handlers
:当前root logger
的handlers
的id
列表1version:1
2root:
3 level:DEBUG
4 handlers:[filehandler, ]
5loggers:
6 console:
7 level:WARNING
8 handlers:[consolehandler,]
9 propagate:1
10handlers:
11 filehandler:
12 class:logging.FileHandler
13 filename:logs/sys.log
14 level:WARNING
15 formatter:fileformatter
16 consolehandler:
17 class:logging.StreamHandler
18 stream:ext://sys.stdout
19 level:DEBUG
20 formatter:consoleformatter
21formatters:
22 fileformatter:
23 format:'%(asctime)s [%(name)s][%(levelname)s]:%(message)s'
24 consoleformatter:
25 format:'%(asctime)s[%(levelname)s]:%(message)s'
复制代码
外部对象访问:外部对象是指不能直接进行访问,须要
import
导入的对象,这时候须要加一个ext://
前缀以便识别,而后系统就会import
这个前缀后面的内容。
参考资料:
Python日志库logging总结-多是目前为止将logging库总结的最好的一篇文章
python基础学习十 logging模块详细使用【转载】 - louis_w - 博客园
Python之路(第十七篇)logging模块 - Nicholas- - 博客园