python配置日志的几种方式
使用的是logging模块,关于logging模块内容,可以看我的另一篇博客:https://www.cnblogs.com/kuxingseng95/p/9464347.html
作为开发者,我们一般使用三种方式来配置logging:
- 使用Python代码显式的创建loggers, handlers和formatters并分别调用它们的配置函数;
- 创建一个日志配置文件,然后使用
fileConfig()
函数来读取该文件的内容; - 创建一个包含配置信息的dict,然后把它传递个
dictConfig()
函数;
需要说明的是,logging.basicConfig()
也属于第一种方式,它只是对loggers, handlers和formatters的配置函数进行了封装。另外,第二种配置方式相对于第一种配置方式的优点在于,它将配置信息和代码进行了分离,这一方面降低了日志的维护成本,同时还使得非开发人员也能够去很容易地修改日志配置。
使用python代码实现日志配置
import logging
import sys
# 创建一个日志器logger并设置其日志级别为DEBUG
logger = logging.getLogger('simple_logger')
logger.setLevel(logging.DEBUG) # 创建一个流处理器handler并设置其日志级别为DEBUG
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.DEBUG) # 创建一个格式器formatter并将其添加到处理器handler
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter) # 为日志器logger添加上面创建的处理器handler
logger.addHandler(handler) # 日志输出
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message') # 运行结果
# 2018-08-15 08:43:57,794 - simple_logger - DEBUG - debug message
# 2018-08-15 08:43:57,794 - simple_logger - INFO - info message
# 2018-08-15 08:43:57,796 - simple_logger - WARNING - warn message
# 2018-08-15 08:43:57,796 - simple_logger - ERROR - error message
# 2018-08-15 08:43:57,796 - simple_logger - CRITICAL - critical message
使用配置文件配置日志
python代码中
import logging.config # 读取日志配置文件内容
logging.config.fileConfig('logging.conf') # 创建一个日志器logger
logger = logging.getLogger('simpleExample') # 日志输出
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
创建配置文件:logging.conf:
[loggers]
keys=root,simpleExample [handlers]
keys=fileHandler,consoleHandler [formatters]
keys=simpleFormatter [logger_root]
level=DEBUG
handlers=fileHandler [logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate= [handler_consoleHandler]
class=StreamHandler
args=(sys.stdout,)
level=DEBUG
formatter=simpleFormatter [handler_fileHandler]
class=FileHandler
args=('logging.log', 'a')
level=ERROR
formatter=simpleFormatter [formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
输出为:
-- ::, - simpleExample - DEBUG - debug message
-- ::, - simpleExample - INFO - info message
-- ::, - simpleExample - WARNING - warn message
-- ::, - simpleExample - ERROR - error message
-- ::, - simpleExample - CRITICAL - critical message
说明
该函数实际上是对configparser
模块的封装,关于configparser
模块的介绍请参考<。
函数定义
该函数定义在loging.config模块下:
logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True)
参数:
- fname:表示配置文件的文件名或文件对象
- defaults:指定传给ConfigParser的默认值
- disable_existing_loggers:这是一个布尔型值,默认值为True(为了向后兼容)表示禁用已经存在的logger,除非它们或者它们的祖先明确的出现在日志配置中;如果值为False则对已存在的loggers保持启动状态。
配置文件格式说明
上面提到过,fileConfig()
函数是对ConfigParser/configparser
模块的封装,也就是说fileConfig()
函数是基于ConfigParser/configparser
模块来理解日志配置文件的。换句话说,fileConfig()
函数所能理解的配置文件基础格式是与ConfigParser/configparser
模块一致的,只是在此基础上对文件中包含的section
和option
做了一下规定和限制,比如:
1)配置文件中一定要包含
loggers
、handlers
、formatters
这些section,它们通过keys
这个option来指定该配置文件中已经定义好的loggers、handlers和formatters,多个值之间用逗号分隔;另外loggers
这个section中的keys一定要包含root这个值;2)
loggers
、handlers
、formatters
中所指定的日志器、处理器和格式器都需要在下面以单独的section进行定义。seciton的命名规则为[logger_loggerName]
、[formatter_formatterName]
、[handler_handlerName]
3)定义logger的section必须指定
level
和handlers
这两个option,level
的可取值为DEBUG
、INFO
、WARNING
、ERROR
、CRITICAL
、NOTSET
,其中NOTSET
表示所有级别的日志消息都要记录,包括用户定义级别;handlers
的值是以逗号分隔的handler名字列表,这里出现的handler必须出现在[handlers]这个section中,并且相应的handler必须在配置文件中有对应的section定义;4)对于非root logger来说,除了
level
和handlers
这两个option之外,还需要一些额外的option,其中qualname
是必须提供的option,它表示在logger层级中的名字,在应用代码中通过这个名字得到logger;propagate
是可选项,其默认是为1,表示消息将会传递给高层次logger的handler,通常我们需要指定其值为0,这个可以看下下面的例子;另外,对于非root logger的level如果设置为NOTSET,系统将会查找高层次的logger来决定此logger的有效level。5)定义handler的section中必须指定
class
和args
这两个option,level
和formatter
为可选option;class
表示用于创建handler的类名,args
表示传递给class
所指定的handler类初始化方法参数
,它必须是一个元组(tuple)的形式,即便只有一个参数值也需要是一个元组的形式;level
与logger中的level一样,而formatter
指定的是该处理器所使用的格式器,这里指定的格式器名称必须出现在formatters
这个section中,且在配置文件中必须要有这个formatter的section定义;如果不指定formatter则该handler将会以消息本身作为日志消息进行记录,而不添加额外的时间、日志器名称等信息;6)定义formatter的sectioin中的option都是可选的,其中包括
format
用于指定格式字符串,默认为消息字符串本身;datefmt
用于指定asctime的时间格式,默认为'%Y-%m-%d %H:%M:%S'
;class
用于指定格式器类名,默认为logging.Formatter;
说明:
配置文件中的
class
指定类名时,该类名可以是相对于logging模块的相对值,如:FileHandler
、handlers.TimeRotatingFileHandler
;也可以是一个绝对路径值,通过普通的import机制来解析,如自定义的handler类mypackage.mymodule.MyHandler
,但是mypackage需要在Python可用的导入路径中--sys.path。
对于propagate属性的说明
实例1:
我们把logging.conf
中simpleExample这个handler定义中的propagate属性值改为1,或者删除这个option(默认值就是1):
[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=
现在来执行同样的代码:
# 读取日志配置文件内容
logging.config.fileConfig('logging.conf') # 创建一个日志器logger
logger = logging.getLogger('simpleExample') # 日志输出
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
我们会发现,除了在控制台有输出信息时候,在logging.log文件中也有内容输出:
2018-08-15 09:26:08,922 - simpleExample - ERROR - error message
2018-08-15 09:26:08,922 - simpleExample - CRITICAL - critical message
这说明simpleExample这个logger在处理完日志记录后,把日志记录传递给了上级的root logger再次做处理,所有才会有两个地方都有日志记录的输出。通常,我们都需要显示的指定propagate的值为0,防止日志记录向上层logger传递。
实例2:
现在,我们试着用一个没有在配置文件中定义的logger名称来获取logger:
# 读取日志配置文件内容
logging.config.fileConfig('logging.conf') # 用一个没有在配置文件中定义的logger名称来创建一个日志器logger
logger = logging.getLogger('simpleExample1') # 日志输出
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
运行程序后,我们会发现控制台没有任何输出,而logging.log文件中又多了两行输出:
-- ::, - simpleExample1 - ERROR - error message
-- ::, - simpleExample1 - CRITICAL - critical message
这是因为,当一个日志器没有被设置任何处理器是,系统会去查找该日志器的上层日志器上所设置的日志处理器来处理日志记录。simpleExample1在配置文件中没有被定义,因此logging.getLogger(simpleExample1)
这行代码这是获取了一个logger实例,并没有给它设置任何处理器,但是它的上级日志器--root logger在配置文件中有定义且设置了一个FileHandler处理器,simpleExample1处理器最终通过这个FileHandler处理器将日志记录输出到logging.log文件中了。
使用字典配置日志信息
Python 3.2中引入的一种新的配置日志记录的方法--用字典来保存logging配置信息。这相对于上面所讲的基于配置文件来保存logging配置信息的方式来说,功能更加强大,也更加灵活,因为我们可把很多的数据转换成字典。比如,我们可以使用JSON格式的配置文件、YAML格式的配置文件,然后将它们填充到一个配置字典中;或者,我们也可以用Python代码构建这个配置字典,或者通过socket接收pickled序列化后的配置信息。总之,你可以使用你的应用程序可以操作的任何方法来构建这个配置字典。
实际中经常用json和yaml配置,所以我写了一个简单的函数,用来启动日志记录:
import logging.config
import json
import os
import yaml def setup_logging(default_path="logging.json", default_level=logging.INFO, env_key="LOG_CFG"):
path = default_path
value = os.getenv(env_key, None)
if value:
path = value if os.path.exists(path) and os.path.splitext(path)[1] == ".json":
with open(path, 'r') as f_conf:
dict_conf = json.load(f_conf)
logging.config.dictConfig(dict_conf)
elif os.path.exists(path) and os.path.splitext(path)[1] == ".yaml":
with open(path, 'r') as f_conf:
dict_conf = yaml.load(f_conf)
logging.config.dictConfig(dict_conf)
else:
logging.basicConfig(level=default_level)
通过json文件配置
创建json配置文件logging.json:
{
"version": 1,
"disable_existing_loggers": false,
"formatters": {
"simple": {
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
}
}, "handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "simple",
"stream": "ext://sys.stdout"
}, "info_file_handler": {
"class": "logging.handlers.RotatingFileHandler",
"level": "INFO",
"formatter": "simple",
"filename": "info.log",
"maxBytes": 10485760,
"backupCount": 20,
"encoding": "utf8"
}, "error_file_handler": {
"class": "logging.handlers.RotatingFileHandler",
"level": "ERROR",
"formatter": "simple",
"filename": "errors.log",
"maxBytes": 10485760,
"backupCount": 20,
"encoding": "utf8"
}
}, "loggers": {
"my_module": {
"level": "ERROR",
"handlers": ["console"],
"propagate": "yes"
}
}, "root": {
"level": "INFO",
"handlers": ["console", "info_file_handler", "error_file_handler"]
}
}
使用上面自定义的函数:
if __name__ == "__main__":
setup_logging(default_path="logging.json")
logging.debug('debug message')
logging.info('info message')
logging.warn('warn message')
logging.error('error message')
logging.critical('critical message')
通过yaml文件配置
使用yaml文件配置首先要安装PyYAML模块
pip install PyYAML
创建yaml配置文件logging.yaml:
version: 1 disable_existing_loggers: False formatters:
simple:
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s" handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext://sys.stdout info_file_handler:
class: logging.handlers.RotatingFileHandler
level: INFO
formatter: simple
filename: info.log
maxBytes: 10485760 # 10MB
backupCount: 20
encoding: utf8 error_file_handler:
class: logging.handlers.RotatingFileHandler
level: ERROR
formatter: simple
filename: errors.log
maxBytes: 10485760 # 10MB
backupCount: 20
encoding: utf8 loggers:
my_module:
level: ERROR
handlers: [console]
propagate: no root:
level: INFO
handlers: [console, info_file_handler, error_file_handler]
使用上面自定义的函数:
if __name__ == "__main__":
setup_logging(default_path="logging.yaml")
logging.debug('debug message')
logging.info('info message')
logging.warn('warn message')
logging.error('error message')
logging.critical('critical message')
说明
关于json和yaml
使用json的好处就是json是一个标准库,不需要额外安装,使用yaml的好处就是好读好写。
关于dicConfig()函数的说明
该函数实际上是对configparser
模块的封装,关于configparser
模块的介绍请参考<。
函数定义:
该函数定义在loging.config模块下:
logging.config.dictConfig(config)
该函数可以从一个字典对象中获取日志配置信息,config参数就是这个字典对象。关于这个字典对象的内容规则会在下面进行描述。
配置说明
无论是上面提到的配置文件,还是这里的配置字典,它们都要描述出日志配置所需要创建的各种对象以及这些对象之间的关联关系。比如,可以先创建一个名额为“simple”的格式器formatter;然后创建一个名为“console”的处理器handler,并指定该handler输出日志所使用的格式器为"simple";然后再创建一个日志器logger,并指定它所使用的处理器为"console"。
传递给dictConfig()函数的字典对象只能包含下面这些keys,其中version
是必须指定的key,其它key都是可选项:
比如handlers的定义示例:
handlers:
console:
class : logging.StreamHandler
formatter: brief
level : INFO
filters: [allow_foo]
stream : ext://sys.stdout
file:
class : logging.handlers.RotatingFileHandler
formatter: precise
filename: logconfig.log
maxBytes: 1024
backupCount: 3
关于外部对象的访问
需要说明的是,上面所使用的对象并不限于loggging模块所提供的对象,我们可以实现自己的formatter或handler类。另外,这些类的参数也许需要包含sys.stderr这样的外部对象。如果配置字典对象是使用Python代码构造的,可以直接使用sys.stdout、sys.stderr;但是当通过文本文件(如JSON、YAML格式的配置文件)提供配置时就会出现问题,因为在文本文件中,没有标准的方法来区分sys.stderr
和字符串'sys.stderr'
。为了区分它们,配置系统会在字符串值中查找特定的前缀,例如'ext://sys.stderr'中'ext://'会被移除,然后import sys.stderr
。
【转】 向日志输出中添加上下文信息:http://www.cnblogs.com/yyds/p/6897964.html
python配置日志的几种方式的更多相关文章
- Python 配置日志的几种方式
Python配置日志的几种方式 作为开发者,我们可以通过以下3种方式来配置logging: (1)使用Python代码显式的创建loggers,handlers和formatters并分别调用它们的配 ...
- 【转】python之配置日志的几种方式
[转]python之配置日志的几种方式 作为开发者,我们可以通过以下3种方式来配置logging: 1)使用Python代码显式的创建loggers, handlers和formatters并分别调用 ...
- python之配置日志的三种方式
以下3种方式来配置logging: 1)使用Python代码显式的创建loggers, handlers和formatters并分别调用它们的配置函数: 2)创建一个日志配置文件,然后使用fileCo ...
- Python之配置日志的几种方式(logging模块)
原文:https://blog.csdn.net/WZ18810463869/article/details/81147167 作为开发者,我们可以通过以下3种方式来配置logging: 1)使用Py ...
- python之配置日志的几种方式
作为开发者,我们可以通过以下3种方式来配置logging: 1)使用Python代码显式的创建loggers, handlers和formatters并分别调用它们的配置函数: 2)创建一个日志配置文 ...
- Spring Boot配置过滤器的两种方式
过滤器(Filter)是Servlet中常用的技术,可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,常用的场景有登录校验.权限控制.敏感词过滤等,下面介绍下Spring Boot配置过 ...
- 通过filebeat、logstash、rsyslog采集nginx日志的几种方式
由于nginx功能强大,性能突出,越来越多的web应用采用nginx作为http和反向代理的web服务器.而nginx的访问日志不管是做用户行为分析还是安全分析都是非常重要的数据源之一.如何有效便捷的 ...
- 【转】Apache 配置虚拟主机三种方式
Apache 配置虚拟主机三种方式 原文博客http://www.cnblogs.com/hi-bazinga/archive/2012/04/23/2466605.html 一.基于IP 1. 假 ...
- spring配置属性的两种方式
spring配置属性有两种方式,第一种方式通过context命名空间中的property-placeholder标签 <context:property-placeholder location ...
随机推荐
- Mybatis学习笔记17 - sql标签和include标签
示例代码: 接口定义: package com.mybatis.dao; import com.mybatis.bean.Employee; import org.apache.ibatis.anno ...
- java多线程(四)
一个例子: Account.java 客户实体类 package com.asiainfo.test.thread8; /** * 账户类 * @author luke * */ public cla ...
- Cookie和Session入门(一)
目录一)背景介绍二)Cookie机制三)Session机制四)两者比较五)参考资料链接一)背景介绍Cookie与Session是常用的会话跟踪技术.1.Cookie通过在客户端记录信息确定用户身份,S ...
- kmspico
# process | 在这儿找到了原作者的地址 http://blog.nsfocus.net/kmspico/ | 下面是原作者地址 https://forums.mydigitallife.ne ...
- inventor安装失败怎样卸载安装inventor 2018?
AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...
- Vertex And Fragment Shader(顶点和片段着色器)
Vertex And Fragment Shader(顶点和片段着色器) Shader "Unlit/ Vertex_And_Fragment_Shader " { Proper ...
- web.xml文件配置详解以及实例说明
1.web.xml学名叫部署描述符文件,是在Servlet规范中定义的,是web应用的配置文件. 2.部署描述符文件就像所有XML文件一样,必须以一个XML头开始.这个头声明可以使用的XML版本并给出 ...
- lftp 快速使用
登录 lftp username:password@ip:port 设置字符集 set ftp:charset 'gbk' set ftp:charset 'utf-8' 下载文件 mget *.tx ...
- 浅析正则表达式模式匹配的 String 方法
在JavaScript代码中使用正则表达式进行模式匹配经常会用到String对象和RegExp对象的一些方法,例如replace.match.search等方法,以下是对一些方法使用的总结. Stri ...
- PHP运行机制
PHP运行机制: 访问html文件:访问的域名à解析成IP地址(hosts文件,dns)à找到服务器àapache拿到html文件à返回给浏览器à浏览器解析html内容 访问php文件:apache拿 ...