简述
日志系统是软件开发,调试,运维的过程必不可缺的元素
本文从简单的日志使用,日志各模块详细介绍python日志系统
简单的例子
输出到控制台
>>> import logging
>>> logging.warning("watch out!")
WARNING:root:watch out!
输出到文件
import logging
logging.basicConfig(filename='tmp.log',level=logging.DEBUG)
logging.debug('log file')
日志级别
DEBUG 调试详细信息
INFO 事情按照预期工作
WARNING 警告
ERROR 错误,软件一部分不能执行
CRITICAL 严重错误,表明软件已经不能继续运行
logging库详细介绍
logger 可以直接调用的接口
handler 日志记录发送到合适的目的地
filter 过滤器,决定输出哪条记录
formatter 输出记录的最终格式
logger
日志记录是通过调用logger的实例方法实现的,用.
做分隔符
创建方法logger = logging.getLogger(logger_name)
当没有显示的创建时,会默认创建root logger,默认日志级别warning,处理器handler将日志信息打印到标准输出,默认格式第一个简单实用程序中输出的格式
logger.setLevel(logging.INFO) #设置日志级别为INFO,只有日志级别大于INFO的才会输出
logger.addHandler(handler_name) #为logger对象增加处理器
logger.removeHandler(handler_name)
handler
```logger```通过```addHandler()```方法给它自己添加零个或者多个处理器
创建handler之后通过下面的方法来设定日志级别,设定格式,添加一个或多个过滤器
setLevel(logging.WARN) # 指定日志级别,低于WARN级别的日志将被忽略 setFormatter(formatter_name) # 设置一个格式化器formatter addFilter(filter_name) # 增加一个过滤器,可以增加多个 removeFilter(filter_name) # 删除一个过滤器
为什么会有两个setLevel()方法,记录器的级别决定了消息是否要传递给处理器。每个处理器的级别决定了消息是否要分发。
#### logging.StreamHandler
StreamHandler将日志输出发送到```sys.stdout```, ```sys.stderr```这样的流对象
```sh = logging.StreamHandler(stream=None)```
```stream```是一个文件对象,默认是sys.stderr
#### logging.FileHandler
```fh = logging.FileHandler(filename, mode='a', encoding=None, delay=False)```
默认为追加方式打开文件
#### RotatingFileHandler和TimedRotatingFileHandler
logging.handlers.RotatingFileHandler(filename, mode=’a’, maxBytes=0, backupCount=0, encoding=None, delay=0)
以文件大小为阈值,改名并重建新的日志文件,
改名规则:日志名字为tmp.log,达到阈值更改为tmp.log.1存储,若tmp.log.1存在类推为tmp.log.2或者后续数字,tmp.log就像临时存储文件
```maxBytes```指定阈值大小,当maxBytes=0,日志文件可以无限大
```backupCount```只保存指定数量的日志,会覆盖前面的日志 #TODO
logging.handlers.TimedRotatingFileHandler(filename, when=’h’, interval=1, backupCount=0, encoding=None, delay=False, utc=False)
间隔一定时间创建日志
```interval```是时间间隔
```when```时间间隔单位,不区分大小写,有以下取值
S 秒 M 分 H 小时 D 天 W 每星期(interval==0时代表星期一) midnight 每天凌晨
#### SocketHandler
logging.handlers.SocketHandler logging.handlers.DatagramHandler
以上两个```Handler```类似,都是将日志信息发送到网络。不同的是前者使用```TCP```协议,后者使用```UDP```协议。它们的构造函数是:
```Handler(host, port)```
其中```host```是主机名,```port```是端口名
#### TODO
还有多种不常用handler,以及delay参数
### Formatter
```logging.Formatter(fmt=None, datefmt=None)```
使用```Formatter```对象设置日志信息最后的规则、结构和内容,默认的时间格式为```%Y-%m-%d %H:%M:%S```。
其中,```fmt```是消息的格式化字符串,```datefmt```是日期字符串。如果不指明```fmt```,将使用```%(message)s```。如果不指明```datefmt```,将使用```ISO8601```日期格式。
日志系统可以输出的各种信息
%(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 用户输出的消息
### Filter
```Filter```基类只允许特定```Logger```层次以下的事件。例如用```A.B```初始化的```Filter```允许```Logger``` ```A.B```, ```A.B.C```, ```A.B.C.D```, ```A.B.D```等记录的事件,```logger``` ```A.BB```, ```B.A.B``` 等就不行。 如果用空字符串来初始化,所有的事件都接受。
```filter = logging.Filter(name='')```
## 配置日志
### 使用源码
import logging
formatter = logging.Formatter(‘%(asctime)s %(filename)s %(name)s %(message)s ‘ )
sh = logging.StreamHandler(stream=None) sh.setLevel(logging.INFO) sh.setFormatter(formatter)
logger = logging.getLogger(‘test_logger’) logger.setLevel(logging.INFO) logger.addHandler(sh) logger.warning(“warning !”)
2016-09-14 22:20:39,693
### 使用配置文件
配置文件必需包含名为```[loggers]```, ```[handlers]``` 和 ```[formatters]```的节,标识了文件中定义的各种类型的对象的名字
[loggers] keys=root,log1
[handlers] keys=handler0,handler1
[formatters] keys=form0,form1
对于每一个实体,会一个独立的节标识如何配置该实体:[loggers]节中有名为log1的logger,就需要有[logger_log1]的节并会包含了相关的配置细节
根logger必需指定级别和handler列表。
level=DEBUG handlers=handler0
```level```可以是```DEBUG```,```INFO```,```WARNING```,```ERROR```,```CRITICAL```或```NOTSET```其中之一。```NOTSET```表示所有的消息都要记录,这只对根```logger```有效
对于非根```logger```来说,需要一些额外的信息。
[logger_log1] level=WARNING handlers=handler1 propagate=1 qualname=log_1
如果非根logger的级别为NOTSET,系统参考高层次的logger来决定logger的有效级别。propagate为1表示将消息传递给高层次logger的handler,为0表示不传播。qualname是logger在层次中的名字,应用通过该名字得到logger,对于不存在的名字均为跟logger
[handler_handler0] class=StreamHandler level=INFO formatter=form0 args=(sys.stderr,)
class表示handler的类
[formatter_form1] format= %(asctime)s %(levelname)s %(message)s datefmt= “%a %d %b %Y %H:%M:%S” class=logging.Formatter
在调用配置文件代码中需要调用```logging.config.fileConfig()```方法:
import logging.config logging.config.fileConfig(‘./logging_emp.conf’) ```
TODO
字典形式配置