前言

python的logging模块是用来设置日志的,是python的标准模块。

系列文章

日志记录的级别

  • DEBUG:优先级10,记录调试的详细信息,只在调试时开启;

  • INFO:优先级20,记录普通的消息,包括错误和警告等等;

  • WARNING:优先级30,记录相关的警告信息;

  • ERROR:优先级40,记录错误信息,程序崩溃;

  • CRITICAL:优先级50,记录错误信息;

如果不设置级别的话,默认为warning,系统记录设置的日志级别优先级以上的日志信息。

logging模块的主要结构

查看logging的源码,可知主要有四个类实现功能;

  • Loggers:提供应用程序直接使用的接口,如相关的配置设置;

  • Handlers:将Loggers产生的日志传到指定位置,设置日志保存的位置;

  • Filters:对输出日志进行过滤操作;

  • Formatters:控制日志的输出格式;

Formatters

Formatter对象定义了日志的输出格式,有多种可选参数。

%(name)s Logger的名字
%(levelno)s 数字形式的日志级别
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名|
%(funcName)s 调用日志输出函数的函数名|
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮点数表示|
%(relativeCreated)d 输出日志信息时的,自Logger创建以来的毫秒数|
%(asctime)s 字符串形式的当前时间。默认格式是“2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有
%(message)s 用户输出的消息 # 定义一个输出格式的对象
formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s',datefmt='%Y-%m-%d %H:%M:%S', style='%') # Formatter参数:
fmt:定义输出的日志信息的格式;
datefmt:定义时间信息的格式,默认为'%Y-%m-%d %H:%M:%S';
style:定义格式化输出的占位符,默认是%(name)格式,可选{}或$格式

Handlers日志处理器

日志处理器用来处理日志的具体流向,是输出到文件中还是到标准输出等,它通过设置Formatter控制输出格式,添加filters过滤日志;

  • 常见的处理器有两种:

StreamHandler:用于向控制台打印日志;

FileHandler:用于向日志文件打印日志;

  • 其它的处理器
RotatingHandler:logging.handlers.RotatingHandler;日志回滚方式,支持日志文件最大数量和日志文件回滚
TimeRotatingHandler:logging.handlers.TimeRotatingHandler;日志回滚方式,在一定时间区域内回滚日志文件
SocketHandler:logging.handlers.SocketHandler;远程输出日志到TCP/IP sockets
DatagramHandler:logging.handlers.DatagramHandler;远程输出日志到UDP sockets
SMTPHandler:logging.handlers.SMTPHandler;远程输出日志到邮件地址
SysLogHandler:logging.handlers.SysLogHandler;日志输出到syslog
NTEventLogHandler:logging.handlers.NTEventLogHandler;远程输出日志到Windows NT/2000/XP的事件日志
MemoryHandler:logging.handlers.MemoryHandler;日志输出到内存中的指定buffer
HTTPHandler:logging.handlers.HTTPHandler;通过"GET"或者"POST"远程输出到HTTP服务器
from logging import Handler
handler = Handler() # 所有上述处理器的父类
print(handler.level) # 处理日志的等级
print(handler.name) # 处理日志的名字
print(handler.filters) # 处理器的日志过滤器
print(handler.formatter) # 日志的格式 handler.get_name()
handler.set_name('') handler.createLock() # 创建线程锁
handler.acquire() # 获取线程锁
handler.release() # 释放线程锁
handler.setLevel('info') # 设置日志处理器的记录级别
handler.setFormatter(fmt='') # 设置日志的输出格式 handler.addFilter('') # 往处理器中添加过滤器
handler.removeFilter('') # 往处理器中移除过滤器 handler.emit('') # 日志记录的处理逻辑,由子类实现

Logger日志对象

Logger管理着所有记录日志的方法。

logger = getLogger(__name__) # 返回一个Logger实例
# logger = getLogger('root') # 以'root'为名字的日志对象在Logger对象中只有一个实例 # 如果是想调用以'root'为名字的日志对象输出日志,可以直接导入
from logging import error, debug, warning, info, fatal, critical print(logger.root) # 获取根日志对象
print(logger.manager) # 获取manager
print(logger.name) # 日志对象的名字
print(logger.level) # 日志记录水平
print(logger.filters) # 日志过滤器列表
print(logger.handlers) # 日志处理器列表
print(logger.disabled) logger.setLevel('info') # 设置日志记录水平 logger.info('this is %s', 'info', exc_info=1) # 输出日志信息,格式化输出
logger.warning('') # 记录warning信息
logger.error('') # 记录error信息
logger.exception('') # 等价于logger.error('', exc_info=1)
logger.debug('') # 记录debug信息
logger.critical('') # 记录critical信息
logger.log('info','') # 直接指定级别 logger.addHandler('') # 添加处理器
logger.removeHandler('') # 移除处理器
logger.hasHandlers() # 判断是否有处理器

logger的基本使用

import logging
import sys def get_logger(appname):
# 获取logger实例,如果参数为空则返回root logger
logger = logging.getLogger(appname)
# 创建日志输出格式
formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s') # 设置文件处理器,加载处理格式
file_handler = logging.FileHandler("test.log") # 指定输出的文件路径
file_handler.setFormatter(formatter) # 控制台日志
console_handler = logging.StreamHandler(sys.stdout)
console_handler.formatter = formatter # 为logger添加的日志处理器
logger.addHandler(file_handler)
logger.addHandler(console_handler) # 指定日志的最低输出级别,默认为WARN级别
logger.setLevel(logging.INFO) if __name__ == "__main__":
logger = get_logger('test')
logger.debug('this is debug info')
logger.info('this is information')
logger.warn('this is warning message')
logger.error('this is error message')
logger.fatal('this is fatal message, it is same as logger.critical')
logger.critical('this is critical message')

logger日志记录的逻辑调用过程

  1. 记录日志通过调用logger.debug等方法;

  2. 首先判断本条记录的日志级别是否大于设置的级别,如果不是,直接pass,不再执行;

  3. 将日志信息当做参数创建一个LogRecord日志记录对象;

  4. 将LogRecord对象经过logger过滤器过滤,如果被过滤掉则pass;

  5. 日志记录对象被Handler处理器的过滤器过滤;

  6. 判断本条记录的日志级别是否大于Handler处理器设置的级别,如果不是,直接pass,不再执行,最后调用处理器的emit方法处理日志记录;

配置logger

  1. 通过代码进行完整配置,主要是通过getLogger方法实现,但不好修改;
  2. 通过basicConfig方法实现,这种方式快速但不够层次分明;
  3. 通过logging.config.fileConfig(filepath),文件配置。
  4. 通过dictConfig的字典方式配置,这是py3.2版本引入的新的配置方法;

使用文件方式配置

# logging.conf

[loggers]    # 定义日志的对象名称是什么,注意必须定义root,否则报错。
keys=root,main [handlers] # 定义处理器的名称是什么,可以有多个,用逗号隔开
keys=consoleHandler [formatters] # 定义输出格式对象的名称,可以有多个,用逗号隔开
keys=simpleFormatter [logger_root] # 配置root对象的日志记录级别和使用的处理器
level=INFO
handlers=consoleHandler [logger_main] # 配置main对象的日志记录级别和使用的处理器,qualname值得就是日志对象的名字
level=INFO
handlers=consoleHandler
qualname=main
propagate=0 # logger对象把日志记录传递给所有相关的handler的时候,会(逐级向上)寻找这个logger和它所有的父logger的全部handler,propagate=1表示会继续向上搜寻;propagate=0表示停止搜寻,这个参数涉及重复打印的坑。 [handler_consoleHandler] # 配置处理器consoleHandler
class=StreamHandler
level=WARNING
formatter=simpleFormatter
args=(sys.stdout,) [formatter_simpleFormatter] # 配置输出格式过滤器simpleFormatter
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
  • 注意:可以看到logger和Handler都可以设置日志级别,日志输出是取最高级别。

使用字典形式配置

字典形式配置功能更加强大,也更加灵活。通过dictConfig函数,我们可以将其他格式的配置文件先转化成字典,如json、YAML等。

import yaml
from logging.config import dictConfig
import os
filename = os.path.dirname(os.path.abspath(__file__))
with open(filename + '\logging.yml', 'r') as f:
log = yaml.load(f.read())
dictConfig(log)
# logging.yaml
version: 1
formatters:
simple:
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext://sys.stdout
console_err:
class: logging.StreamHandler
level: DEBUG
formatter: simple
stream: ext://sys.stderr
loggers:
simpleExample:
level: DEBUG
handlers: [console]
propagate: no
root:
level: DEBUG
handlers: [console_err]

一些细节

  • logger的继承

logging.getLogger(appname),同一个appname获取到的logger对象是同一个,同时appname.name命名的logger继承了appname的所有的属性,可以不用重新配置logger。

  • 输出错误信息的方法
try:
raise
except:
logger.error('this is error message',exc_info = True)
# 或
logger.exception("Failed to open sklearn.txt from logger.exception") # 设置exc_info为True后,会自动将错误的信息也发送到日志中;
# 直接使用exception实现一样的功能。

监听logger配置更改

  • logging.config.listen(port)函数可以让应用程序在一个socket上监听新的配置信息,达到在运行时改变配置,而不用重启应用程序的目的。
import logging.config
import logging
import time logging.config.fileConfig("logging.conf")
logger = logging.getLogger("test.listen") t = logging.config.listen(9999)
t.setDaemon(True)
t.start() # 启动监听服务器

参考

python模块分析之logging日志(四)的更多相关文章

  1. 【转】python模块分析之logging日志(四)

    [转]python模块分析之logging日志(四) python的logging模块是用来写日志的,是python的标准模块. 系列文章 python模块分析之random(一) python模块分 ...

  2. Python模块04/包/logging日志

    Python模块04/包/logging日志 目录 Python模块04/包/logging日志 内容大纲 1.包 2.logging日志 3.今日总结 内容大纲 1.包 2.logging日志 1. ...

  3. Python模块学习:logging 日志记录

    原文出处: DarkBull    许多应用程序中都会有日志模块,用于记录系统在运行过程中的一些关键信息,以便于对系统的运行状况进行跟踪.在.NET平台中,有非常著名的第三方开源日志组件log4net ...

  4. 【转】python模块分析之collections(六)

    [转]python模块分析之collections(六) collections是Python内建的一个集合模块,提供了许多有用的集合类. 系列文章 python模块分析之random(一) pyth ...

  5. 【转】python模块分析之unittest测试(五)

    [转]python模块分析之unittest测试(五) 系列文章 python模块分析之random(一) python模块分析之hashlib加密(二) python模块分析之typing(三) p ...

  6. 【转】python模块分析之typing(三)

    [转]python模块分析之typing(三) 前言:很多人在写完代码一段时间后回过头看代码,很可能忘记了自己写的函数需要传什么参数,返回什么类型的结果,就不得不去阅读代码的具体内容,降低了阅读的速度 ...

  7. python模块分析之typing(三)

    前言:很多人在写完代码一段时间后回过头看代码,很可能忘记了自己写的函数需要传什么参数,返回什么类型的结果,就不得不去阅读代码的具体内容,降低了阅读的速度,加上Python本身就是一门弱类型的语言,这种 ...

  8. 【转】python模块分析之hashlib加密(二)

    [转]python模块分析之hashlib加密(二) hashlib模块是用来对字符串进行hash加密的模块,明文与密文是一一对应不变的关系:用于注册.登录时用户名.密码等加密使用.一.函数分析:1. ...

  9. python 自动化之路 logging日志模块

    logging 日志模块 http://python.usyiyi.cn/python_278/library/logging.html 中文官方http://blog.csdn.net/zyz511 ...

随机推荐

  1. MT【52】空间法向量理解直线条数

    [从最简单的做起.]--波利亚 评:线面角转化成线与线的角,这道题还有类似的这类题是学生的难点.

  2. 自学Linux Shell3.5-目录处理命令mkdir rmdir

    点击返回 自学Linux命令行与Shell脚本之路 3.5-目录处理命令mkdir rmdir 1. mkdir命令 创建一个或多个新的目录. mkdir 命令创建由 Directory 参数指定的一 ...

  3. 自学Aruba1.4-Aruba体系结构-产品线

    点击返回:自学Aruba之路 1. Aruba产品线 IP switches: 1500.2500.3500 Controllers:7200 .70x0 Series.7005 Meridian:基 ...

  4. idea tomcat上传图片,无法显示的问题解决

    真是浪费时间啊,之前eclipse下的tomcat 去webapps下找就行了,这倒好,idea下根本没有. 我上传的目录建在项目中的static中了,upload文件夹,上传到这里肯定是找不到了的: ...

  5. 警告: No data sources are configured to run this SQL and provide advanced code assistance. Disable this inspection via problem menu (Alt+Enter). more... (Ctrl+F1) SQL dialect is not configured. Postgr

    python3出现问题: 警告: No data sources are configured to run this SQL and provide advanced code assistance ...

  6. (大数)Computer Transformation hdu1041

    Computer Transformation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/ ...

  7. ADO.NET连接字符串大全

    说明ADO.NET连接字符串:SQL Server,SQL Server 2005,ACCESS,Oracle,MySQL,Interbase,IBM DB2,Sybase,Informix,Ingr ...

  8. InfluxDB1.2.4部署(centos6.8)

    InfluxDB介绍 官网:https://www.influxdata.com/ 文档:https://docs.influxdata.com/influxdb/v1.2/introduction/ ...

  9. mysql 缓存机制

    了解mysql缓存吗(顺丰) mysql缓存机制就是缓存sql 文本及缓存结果,用KV形式保存再服务器内存中,如果运行相同的sql,服务器直接从缓存中去获取结果,不需要在再去解析.优化.执行sql. ...

  10. NTT模板

    NTT(快速数论变换)用到的各种素数及原根: https://blog.csdn.net/hnust_xx/article/details/76572828 NTT多项式乘法模板 #include&l ...