[TOC]
程序都有记录日志的需求,并且日志中包含的信息既有正常的程序访问日志,还可能有错误、警告等信息输出。
python的logging模块提供了标准的日志接口,可以通过它存储各种格式的日志,logging的日志分为`debug(), info(), warning(), error() and critical()`5个级别。
python默认只打印warning级别以上的日志
## 日志基础
### 两种记录日志的方式:
* 第一种方式是使用logging提供的模块级别的函数
* 第二种方式是使用Logging日志系统的四大组件
>其实模块级别的日志记录函数也是对logging日志系统相关类的封装。
### 模块级别的常用函数
| 函数 | 说明 |
| --- | --- |
| logging.debug(msg, *args, **kwargs) | 创建一条严重级别为DEBUG的日志记录 |
| logging.info(msg, *args, **kwargs) | 创建一条严重级别为INFO的日志记录 |
| logging.warning(msg, *args, **kwargs) | 创建一条严重级别为WARNING的日志记录 |
| logging.error(msg, *args, **kwargs) | 创建一条严重级别为ERROR的日志记录 |
| logging.critical(msg, *args, **kwargs) | 创建一条严重级别为CRITICAL的日志记录 |
| logging.log(level, *args, **kwargs) | 创建一条严重级别为level的日志记录 |
| logging.basicConfig(**kwargs) | 对root logger进行一次性配置 |
>其中`logging.basicConfig(**kwargs)`函数用于指定“要记录的日志级别”、“日志格式”、“日志输出位置”、“日志文件的打开模式”等信息,其他几个都是用于记录各个级别日志的函数。
### logging模块的四大组件
| 组件 | 说明 |
| --- | --- |
| loggers | 提供应用程序代码直接使用的接口 |
| handlers | 将(logger创建的)日志记录发送到合适的目的输出 |
| filters | 提供了细度设备来决定输出哪条日志记录; |
| formatters |决定日志记录的最终输出格式 |
> logging模块提供的模块级别的那些函数实际上也是通过这几个组件的相关实现类来记录日志的,只是在创建这些类的实例时设置了一些默认值。
## 简单使用
### 各级别日志演示
默认只有warning级别以上的日志会打印,见案例
```
>>> import logging
>>> logging.debug('the is debug log')
>>> logging.info('the is info log')
>>> logging.warn('the is warning log')
WARNING:root:the is warning log
>>> logging.error('the is error log')
ERROR:root:the is error log
>>> logging.critical('the is critical log')
CRITICAL:root:the is critical log
>>> logging.log(logging.ERROR,'the is error log 2')
ERROR:root:the is error log 2
```
>每行日志各个字段含义`日志级别:日志器名称:日志内容`
### 修改最低打印的日志级别
```
>>> import logging
>>> logging.basicConfig(level=logging.INFO)
>>> logging.debug('the is debug log')
>>> logging.info('the is info log')
INFO:root:the is info log
```
> 注意`basicConfig`函数是一次性的配置工具,只有在第一次调用该函数时会起作用
### 把日志写到文件
也是用basicConfig方法来修改将日志打印到哪里
```
>>> import logging
>>> logging.basicConfig(filename='tset.log')
>>> logging.info('the is info log')
>>> logging.warn('the is warning log')
>>> logging.error('the is error log')
```
### basicConfig参数列表
| 参数名称 | 描述 |
| --- | --- |
| filename | 指定日志输出目标文件的文件名 |
| filemode | 指定日志文件的打开模式,默认'a'|
| format | 指定日志格式字符串 |
| datefmt | 指定日期/时间格式,需format中包含%(asctime)s字段 |
| level | 指定日志器的日志级别 |
| stream | 指定日志输出目标,如sys.stdout、sys.stderr以及网络stream。stream和filename不能共存 |
| style | 指定format格式字符串的风格,可取值为'%'、'{'和'$',默认为'%' |
| handlers | 该选项如果应该是一个创建了多个Handler的可迭代对象,这些handler将会被添加到root logger。 |
> filename、stream和handlers这三个配置项不能共存,否则会引发异常。
### 自定义日志格式
前面列出了basicConfig的参数,可以根据该参数自定义日志格式
感觉上面的日志格式忘记加上时间啦,日志不知道时间怎么行呢,下面就来加上!
```
>>> import logging
>>> logging.basicConfig(format='%(asctime)s %(message)s',datefmt='%Y-%m-%d %I:%M:%S %p')
>>> logging.error('the is error log')
2019-01-27 10:44:36 AM the is error log
```
### format所有参数列表
| 字段/属性名称 | 使用格式 | 描述 |
| --- | --- | --- |
| asctime | %(asctime)s | 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896” |
| created | %(created)f | 时间戳,就是调用time.time()函数返回的值 |
| msecs | %(msecs)d | 日志发生时间的毫秒部分 |
| levelname | %(levelname)s | 文字形式的日志级别 |
| levelno | %(levelno)s | 数字形式的日志级别(10, 20, 30, 40, 50) |
| name | %(name)s | 使用的日志器名称,默认是'root' |
| message | %(message)s | 日志记录的文本内容,`msg % args`计算得到的 |
| pathname | %(pathname)s | 调用日志记录函数的源码文件的全路径 |
| filename | %(filename)s | pathname的文件名部分,含文件后缀 |
| module | %(module)s | filename的名称部分,不包含后缀 |
| lineno | %(lineno)d | 调用日志记录函数的源代码所在的行号 |
| funcName | %(funcName)s | 调用日志记录函数的函数名 |
| process | %(process)d | 进程ID |
| processName | %(processName)s | 进程名称 |
| thread | %(thread)d | 线程ID |
| threadName | %(thread)s | 线程名称 |
## 其他说明
### 几个要说明的内容:
* `logging.basicConfig()`函数是一个一次性的简单配置工具使,也就是说只有在第一次调用该函数时会起作用,后续再次调用该函数时完全不会产生任何操作的,多次调用的设置并不是累加操作。
* 日志器(Logger)是有层级关系的,上面调用的logging模块级别的函数所使用的日志器是`RootLogger`类的实例,其名称为'root',它是处于日志器层级关系最顶层的日志器,且该实例是以单例模式存在的。
* 如果要记录的日志中包含变量数据,可使用一个格式字符串作为这个事件的描述消息(logging.debug、logging.info等函数的第一个参数),然后将变量数据作为第二个参数\*args的值进行传递,如:`logging.warning('%s is %d years old.', 'Tom', 10)`,输出内容为`WARNING:root:Tom is 10 years old.`
* logging.debug()等方法的定义中,除了msg和args参数外,还有一个**kwargs参数。它们支持3个关键字参数:`exc_info, stack_info, extra`,下面对这几个关键字参数作个说明。
### 关于exc_info, stack_info, extra关键词参数的说明:
* **exc_info:** 其值为布尔值,如果该参数的值设置为True,则会将异常信息添加到日志消息中。如果没有异常信息则添加None到日志信息中。
* **stack\_info:** 其值也为布尔值,默认值为False。如果该参数的值设置为True,栈信息将会被添加到日志信息中。
* **extra:** 这是一个字典(dict)参数,它可以用来自定义消息格式中所包含的字段,但是它的key不能与logging模块定义的字段冲突。
### exc_info, stack_info, extra举例:
在日志消息中添加exc_info和stack_info信息,并添加两个自定义的字端 ip和user
```
LOG_FORMAT = "%(asctime)s - %(levelname)s - %(user)s[%(ip)s] - %(message)s"
DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p"
logging.basicConfig(format=LOG_FORMAT, datefmt=DATE_FORMAT)
logging.warning("Some one delete the log file.", exc_info=True, stack_info=True, extra={'user': 'Tom', 'ip':'47.98.53.222'})
```
输出结果:
```
05/08/2017 16:35:00 PM - WARNING - Tom[47.98.53.222] - Some one delete the log file.
NoneType
Stack (most recent call last):
File "C:/Users/wader/PycharmProjects/LearnPython/day06/log.py", line 45, in <module>
logging.warning("Some one delete the log file.", exc_info=True, stack_info=True, extra={'user': 'Tom', 'ip':'47.98.53.222'})
```
- 基础部分
- 基础知识
- 变量
- 数据类型
- 数字与布尔详解
- 列表详解list
- 字符串详解str
- 元组详解tup
- 字典详解dict
- 集合详解set
- 运算符
- 流程控制与循环
- 字符编码
- 编的小程序
- 三级菜单
- 斐波那契数列
- 汉诺塔
- 文件操作
- 函数相关
- 函数基础知识
- 函数进阶知识
- lambda与map-filter-reduce
- 装饰器知识
- 生成器和迭代器
- 琢磨的小技巧
- 通过operator函数将字符串转换回运算符
- 目录规范
- 异常处理
- 常用模块
- 模块和包相关概念
- 绝对导入&相对导入
- pip使用第三方源
- time&datetime模块
- random随机数模块
- os 系统交互模块
- sys系统模块
- shutil复制&打包模块
- json&pickle&shelve模块
- xml序列化模块
- configparser配置模块
- hashlib哈希模块
- subprocess命令模块
- 日志logging模块基础
- 日志logging模块进阶
- 日志重复输出问题
- re正则表达式模块
- struct字节处理模块
- abc抽象类与多态模块
- requests与urllib网络访问模块
- 参数控制模块1-optparse-过时
- 参数控制模块2-argparse
- pymysql数据库模块
- requests网络请求模块
- 面向对象
- 面向对象相关概念
- 类与对象基础操作
- 继承-派生和组合
- 抽象类与接口
- 多态与鸭子类型
- 封装-隐藏与扩展性
- 绑定方法与非绑定方法
- 反射-字符串映射属性
- 类相关内置方法
- 元类自定义及单例模式
- 面向对象的软件开发
- 网络-并发编程
- 网络编程SOCKET
- socket简介和入门
- socket代码实例
- 粘包及粘包解决办法
- 基于UDP协议的socket
- 文件传输程序实战
- socketserver并发模块
- 多进程multiprocessing模块
- 进程理论知识
- 多进程与守护进程
- 锁-信号量-事件
- 队列与生产消费模型
- 进程池Pool
- 多线程threading模块
- 进程理论和GIL锁
- 死锁与递归锁
- 多线程与守护线程
- 定时器-条件-队列
- 线程池与进程池(新方法)
- 协程与IO模型
- 协程理论知识
- gevent与greenlet模块
- 5种网络IO模型
- 非阻塞与多路复用IO实现
- 带着目标学python
- Pycharm基本使用
- 爬虫
- 案例-爬mzitu美女
- 案例-爬小说
- beautifulsoup解析模块
- etree中的xpath解析模块
- 反爬对抗-普通验证码
- 反爬对抗-session登录
- 反爬对抗-代理池
- 爬虫技巧-线程池
- 爬虫对抗-图片懒加载
- selenium浏览器模拟