“Python日志记录”的版本间的差异
来自CloudWiki
(→logging模块的配置与使用) |
(→日志模块记录到文件) |
||
第48行: | 第48行: | ||
<nowiki>import logging | <nowiki>import logging | ||
logging.basicConfig( | logging.basicConfig( | ||
− | + | filename=r'd:/log1.log' | |
) | ) | ||
+ | while True: | ||
+ | try: | ||
+ | |||
+ | s= input("请输入美元数:") | ||
+ | if s=='q': | ||
+ | break; | ||
+ | else: | ||
+ | s = eval(s) | ||
+ | r = 6.7*s | ||
+ | print("换算为人民币为:",r) | ||
+ | logging.info("info message:换算结果" +str(r)) | ||
− | + | except NameError: | |
− | + | print("用户输入错误") | |
− | + | logging.error("用户输入错误") | |
− | + | ||
− | + | logging.info("循环结束")</nowiki> | |
− | |||
− | |||
− | logging. | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
====实践:程序执行完之后,看看lx_log1.log文件中都发生了什么==== | ====实践:程序执行完之后,看看lx_log1.log文件中都发生了什么==== |
2021年4月25日 (日) 08:16的版本
目录
日志模块
logging模块
运维工作有很多情况需要查问题、解决bug,而查问题和解决bug的过程离不开查看日志,我们编写脚本或程序时总是需要有日志输出,Python的logging模块就是为记录日志使用的,而且是线程安全的,意味着使用它完全不用担心因日志模块的异常导致程序崩溃。
默认情况下,Python的logging模块将日志打印到标准输出中,而且只显示大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL> ERROR > WARNING > INFO > DEBUG)。默认的日志格式:日志级别为Logger,名称为用户输出消息。
日志级别
各日志级别代表的含义如下。
- DEBUG:调试时的信息打印。
- INFO:正常的日志信息记录。
- WARNING:发生了警告信息,但程序仍能正常工作
- ERROR:发生了错误,部分功能已不正常。
- CRITICAL:发生严重错误,程序可能已崩溃。
简单使用
打印到控制台
>>> import logging >>> logging.debug('ddebug message') >>> logging.info('info message') >>> logging.warning('warning') WARNING:root:warning >>> logging.error('error message') ERROR:root:error message >>> logging.critical('critical message') CRITICAL:root:critical message
日志模块记录到文件
import logging logging.basicConfig( filename="./lx_log1.log", # 指定文件位置 ) logging.debug("debug message") logging.info("info message") logging.warning("warning message") logging.error("error message") logging.critical("critical message")
例题:将异常信息写入日志。
import logging logging.basicConfig( filename=r'd:/log1.log' ) while True: try: s= input("请输入美元数:") if s=='q': break; else: s = eval(s) r = 6.7*s print("换算为人民币为:",r) logging.info("info message:换算结果" +str(r)) except NameError: print("用户输入错误") logging.error("用户输入错误") logging.info("循环结束")
实践:程序执行完之后,看看lx_log1.log文件中都发生了什么
思考:为什么info message在文件中没有显示
logging模块的配置与使用
可见在logging.basicConfig()函数中可通过具体参数来更改logging模块的默认行为。
- filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。
- filemode:文件打开方式,在指定了filename时使用这个参数,默认值为a,还可指定为w。
- format:指定handler使用的日志显示格式。
- datefmt:指定日期时间格式。
- level:设置rootlogger的日志级别。
- stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
import logging logging.basicConfig( level=logging.DEBUG, format="%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s", # 日志的格式 datefmt=" %Y-%m-%d %H:%M:%S", # 时间格式 filename="./lx_log1.log", # 指定文件位置 filemode="a", ) logging.debug("debug message") logging.info("info message") logging.warning("warning message") logging.error("error message") logging.critical("critical message")
例题2:
import logging logging.basicConfig( level=logging.DEBUG, format="%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s", # 日志的格式 datefmt=" %Y-%m-%d %H:%M:%S", # 时间格式 filename="./lx_log1.log", # 指定文件位置 filemode="a", ) while True: try: num = input("请输入一个整数: ") if num == 'q': break; num = eval(num) print(num**2) logging.info("info message:input an number" +str(num)) except NameError: print("输入错误,请输入一个整数!") logging.error("input message:输入错误,请输入一个整数") logging.info("end message:退出循环")
日志进阶配置
日志记录器
- logger:记录器,应用程序代码能直接使用的接口。
- handler:处理器,将(记录器产生的)日志记录发送至合适的目的地。
- filter:过滤器,提供了更好的粒度控制,可以决定输出哪些日志记录。
- formatter:格式化器,指明了最终输出中日志记录的布局。
日志事件信息在记录器(logger)、处理器(handler)、过滤器(filter)、格式化器(formatter)之间通过一个日志记录实例来传递。通过调用记录器实例的方法来记录日志,每一个记录器实例都有一个名字,名字相当于其命名空间,是一个树状结构。
例如,一个记录器叫scan,记录器scan.tex、scan.html、scan.pdf的父节点。记录器的名称。可以任意取,但一个比较好的实践是通过下面的方式来命名一个记录器。
import logging # 创建logger,其名称为simple_example,名称为任意,也可为空 logger = logging.getLogger("lx_log2") # 打印logger的名称 print(logger.name) # 设置logger的日志级别 logger.setLevel(logging.INFO) # 创建两个handler,一个负责将日志输出到终端,一个负责输出到文件,并分别设置他们的日志级别 ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) fh = logging.FileHandler(filename="lx_log2.log", mode="a", encoding="utf-8") fh.setLevel(logging.WARNING) # 创建一个格式化器,可以创建不同的格式化器用于不同的handler,这里我们使用一个 formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") # 设置两个handler的格式化器 ch.setFormatter(formatter) fh.setFormatter(formatter) # 为logger添加两个handler logger.addHandler(ch) logger.addHandler(fh) # 在程序中记录日志 logger.debug("debug message") logger.info("info message") logger.warning("warn message") logger.error("error message") logger.critical("critical message")
例题3:
# -*- coding: utf-8 -*- import logging # 创建logger,其名称为simple_example,名称为任意,也可为空 logger = logging.getLogger("lx_log2") # 打印logger的名称 print(logger.name) # 设置logger的日志级别 logger.setLevel(logging.INFO) # 创建两个handler,一个负责将日志输出到终端,一个负责输出到文件,并分别设置他们的日志级别 ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) fh = logging.FileHandler(filename="lx_log2.log", mode="a", encoding="utf-8") fh.setLevel(logging.DEBUG) # 创建一个格式化器,可以创建不同的格式化器用于不同的handler,这里我们使用一个 formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") # 设置两个handler的格式化器 ch.setFormatter(formatter) fh.setFormatter(formatter) # 为logger添加两个handler logger.addHandler(ch) logger.addHandler(fh) # 在程序中记录日志 logger.debug("debug message") logger.info("info message") logger.warning("warn message") logger.error("error message") logger.critical("critical message") try: while(True): num = input("请输入一个整数: ") if num == 'q': break; num = eval(num) print(num**2) logger.info("info message:input an number" +str(num)) logger.info("info message:退出循环") except NameError: print("输入错误,请输入一个整数!") logger.error("error message:输入错误,请输入一个整数")
基于配置文件的配置
日志的配置信息也可以来源于配置文件:
import logging 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')
配置文件:
[loggers] keys=root,simpleExample [handlers] keys=consoleHandler [formatters] keys=simpleFormatter [logger_root] level=DEBUG handlers=consoleHandler [logger_simpleExample] level=DEBUG handlers=consoleHandler qualname=simpleExample propagate=0 [handler_consoleHandler] class=StreamHandler level=DEBUG formatter=simpleFormatter args=(sys.stdout,) [formatter_simpleFormatter] format=%(asctime)s - %(name)s - %(levelname)s - %(message)s datefmt=%Y-%m-%d %H:%M:%S
运行代码后我们会看到lx_log1.py文件的内容如下:
2018-06-07 21:09:51 lx_log1.py[line:9] DEBUG debug message 2018-06-07 21:09:51 lx_log1.py[line:10] INFO info message 2018-06-07 21:09:51 lx_log1.py[line:11] WARNING warning message 2018-06-07 21:09:51 lx_log1.py[line:12] ERROR error message 2018-06-07 21:09:51 lx_log1.py[line:13] CRITICAL critical message
参考文档:《Python自动化运维》