logging 模块:
很多程序都有记录日志的需求, 并且日志中包含的信息既有正常的程序访问日志, 还可能有错误警告等信息输出 Python 的 logging 模块提供了标准的日志接口, 你可以通过它存储各种格式的日志 logging 的日志可以分为 debug()info()warning()error() and critical()5 个级别(按顺序, 级别越来越高)
最简单的用法:
- import logging
- logging.warning(User [neo] attempted wrong password more than 3 times)
- logging.critical(server is down)
- # 运行结果: # 跟 print 没啥区别
- # WARNING:root:User [neo] attempted wrong password more than 3 times
- # CRITICAL:root:server is down
日志级别:
把日志写到文件里:
- import logging
- logging.basicConfig(filename=logging_test.log,level=logging.INFO) # Do basic configuration for the logging system. # level=logging.INFO 的意思是: 只有日志是 INFO 或者比 INFO 级别更高的日志才会被记录在文件里 # 记录日志时, 只会接着以前的日志继续记录, 不会把以前的记录覆盖掉
- logging.debug(debug test)
- logging.info(INFO info)
- logging.warning(Warning!)
- # 运行结果: 把 logging.info 和 logging.warning 记录在了 logging_test.log(.log 的后缀名)这个文件里 # 这种情况下屏幕上没打印, 即 没有输出到屏幕
- # 如下所示:
- # INFO:root:INFO info
- # WARNING:root:Warning!
把时间加到日志里面:
- import logging
- logging.basicConfig(filename=logging_with_time.log,
- level=logging.INFO,
- format=%(asctime)s %(message)s,
- datefmt=%Y-%m-%d %H:%M:%S) # 注意里面的参数 format 和 datefmt
- logging.debug(debug test)
- logging.info(INFO info)
- logging.warning(Warning!)
- # 运行结果: INFO 及其以上级别写入了 logging_with_time.log 文件里面
- # 如下所示:
- # 2018-02-09 11:37:11 INFO info
- # 2018-02-09 11:37:11 Warning!
除了加时间, 还可以自定义其他的格式, 下表就是所有支持的格式:
logging 进阶: 日志同时输出到屏幕和文件:
Python 使用 logging 模块记录日志涉及四个主要的类:
logger 提供了应用程序可以直接使用的接口
handler 将 (logger 创建的) 日志记录发送到合适的目的输出
filter 提供了细度设备来决定输出哪条日志记录
formatter 决定日志记录的最终输出格式
它们之间的关系如下:
logger:
每个程序在输出信息之前都要先获得一个 logger, 如:
- import logging
- # 生成 logger 对象
- logger = logging.getLogger(web) # logger 通常对应了程序的模块名
- # 对 logger 对象设置 Level 级别, 如设置成 INFO 级别
- logger.setLevel(logging.INFO) # 利用 logger.setLevel()对生成的 logger 对象设置级别, logging.INFO 是把级别具体设置成 INFO, 如果你不设置, 系统会默认把 Level 设置成 WARNING # 对 logger 对象设置 level 的作用: loggersetLevel()相当于一个全局变量, 所需要输出的日志需要先经过 logging.getLogger 生成 logger 对象, 所以生成 logger 对象之前, 会先检测所输出的日志级别是否符合 logger.setLevel 的级别, 如果符合则生成 logger 对象; 如果不符合则直接忽略不生成 logger 对象 举例说明: 有两个需要输出的日志: logger.debug(test debug) 和 logger.info(test info) , 执行这两句代码的时候, 由于我已经给生成 logger 设置了 level --- INFO:logger.setLevel(logging.INFO) ,debug 的 level 低于 INFO, 所以 logger.debug(test debug) 不会生成 logger 对象, 但 logger.info(test info) 则会生成 logger 对象(相当于第一步生成 logger 对象时过滤了一部分数据)
- handler:
handler 负责发送相关的信息到指定目的地 Python 日志系统有多种 handler 可以使用可以把信息输出到控制台(屏幕), 也可以把信息输出到文件, 把信息发送到网络上自己也可以编写自己的 handler
每个 logger 可以附加多个 handler 常用的 handler 如下:
logging.StreamHandler # 使用这个 handler 可以向类似于 sys.stdout 或者 sys.stderr 的任何文件对象 (file object) 输出信息(往屏幕上输出)
logging.FileHandler 和 StreamHandler 类似, 用于向一个文件输出日志信息, 不过 FileHandler 会帮你打开这个文件(往文件中输出)
还有两种用法: 一是根据文件大小截断; 二是根据时间 interval 截断 详情参考: https://www.luffycity.com/python-book/di-4-zhang-python-ji-chu-2014-chang-yong-mo-kuai/logging-mo-kuai.html
用法如下:
- #生成logger对象之后,
- 再生成handler对象,
- 然后把handler绑定到logger上#生成handler对象ch = logging.StreamHandler()#负责往屏幕发送的handler(发送到屏幕, 所以括号里面为空) fh = logging.FileHandler(web.log)#负责往文件web.log发送的handler#日志文件的后缀名: .log#把生成的handler对象绑定到logger对象logger.addHandler(ch)#把ch这个handler对象绑定到logger上logger.addHandler(fh)#把fh这个handler对象绑定到logger上#设置handler的level ch.setLevel(logging.INFO)#把ch这个handler对象的level设置成INFO fh.setLevel(logging.WARNING)#把fh这个handler对象的level设置成WARNING#关于设置handler的level,
- 道理跟logger的level设置类似,
- 即: 如果你不设置,
- 程序会默认level是WARNING;通过这一步设置的level能够再次过滤数据#关于logger设置的level和handler设置的level,
- 按照哪个level呢 ? 效果上可以这么理解: 所需要输出的日志 (如: logger.warning(xx)),
- 先经过logger设置的level过滤,
- 然后在生成handler对象这一步,
- 再次经过这一步的level过滤: level符合,
- 则生成相应的handler;
- level不符合则忽略不生成handler对象
formatter 组件:
日志的 formatter 是个独立的组件, 可以跟 handler 组合, 用于设置所要发送的信息以什么样的格式发送到目的地
用法:
- # 生成 handler 对象之后, 再生成 formatter 对象, 然后将 formatter 对象和 handler 绑定
- # 生成 formatter 对象
- console_fmt = logging.Formatter(%(asctime)s - %(name)s - %(levelname)s - %(lineno)d - %(message)s) # 利用上面的 logger 名字表
- file_fmt = logging.Formatter(%(asctime)s - %(name)s - %(levelname)s - %(message)s)
- # 把 formatter 对象绑定到 handler
- ch.setFormatter(console_fmt)
- fh.setFormatter(file_fmt)
下面把上述的代码拼接到一起看效果:
- import logging
- # 生成 logger 对象
- logger = logging.getLogger(web)
- logger.setLevel(logging.INFO)
- # 生成 handler 对象
- ch = logging.StreamHandler()
- fh = logging.FileHandler(web.log)
- # 设置 level
- ch.setLevel(logging.DEBUG)
- fh.setLevel(logging.WARNING)
- # 把 handler 绑定在 logger 上
- logger.addHandler(ch)
- logger.addHandler(fh)
- # 生成 formatter 对象
- console_fmt = logging.Formatter(%(asctime)s - %(name)s - %(levelname)s - %(lineno)d - %(message)s)
- file_fmt = logging.Formatter(%(asctime)s - %(name)s - %(levelname)s - %(message)s) # %(name)s 这个 name 就是生成 logger 时括号里面的 web
- # 把 formatter 绑定到 handler
- ch.setFormatter(console_fmt)
- fh.setFormatter(file_fmt)
- logger.debug(debug test)
- logger.info(info test)
- logger.warning(warning test)
- logger.error(error test)
- logger.critical(critical test) # 输出的日志
filter 的用法参考: https://www.luffycity.com/python-book/di-4-zhang-python-ji-chu-2014-chang-yong-mo-kuai/logging-mo-kuai.html
来源: http://www.bubuko.com/infodetail-2493673.html