坚持写博客,分享自己的在学习、工作中的所得
- 给自己做备忘
- 对知识点记录、总结,加深理解
- 给有需要的人一些帮助,少踩一个坑,多走几步路
尽量以合适的方式排版,图文兼有
如果写的有误,或者有不理解的,均可在评论区留言
如果内容对你有帮助,欢迎点赞 收藏 ⭐留言 。
虽然平台并不会有任何奖励,但是我会很开心,可以让我保持写博客的热情
logging
的使用进行粗浅的解释,可以满足大多数场景的使用,文末也附带了例子可供参考。更多的高大上的用法可自行研究,也希望能一起探讨。
通常我们在写代码时,需要查看或跟踪某个变量或者输出某些信息,都是直接使用print()
在控制台直接输出,这样可以很便捷的看到我们想要的信息。但是如果某个变量的随时变化的,仅仅通过控制台,我们很难看到其变化趋势,或者是代码代码运行过后,在某个时间点又想要查看之前的输出,那么这时就需要将输出持久化。
logging
是一个日志包,可以满足我们对所需内容的跟踪记录包括打印在控制台与文件持久化。
import logging
logging.debug('这是一条debug日志')
logging.info('这是一条info日志')
logging.warning('这是一条warning日志')
logging.error('这是一条error日志')
WARNING:root:这是一条warning日志
ERROR:root:这是一条error日志
从控制台可以看到输出的日志只有上面两条,因为默认的输出日志等级是warning,可以通过设置日志等级来选择过滤的日志。
import logging
logging.basicConfig(filename=None, filemode='a', level=logging.DEBUG)
logging.debug('这是一条debug日志')
logging.info('这是一条info日志')
logging.warning('这是一条warning日志')
logging.error('这是一条error日志')
#DEBUG:root:这是一条debug日志
#INFO:root:这是一条info日志
#WARNING:root:这是一条warning日志
#ERROR:root:这是一条error日志
预定义的日志等级代表的数值:
级别 数值
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0
通过basicConfig
设置日志等级level
,当filename
为None
时,会将过滤后的日志打印在控制台,如果是一个文件名(比如:test.log
或test.txt
),则不会打印而是保存成文件。
从上面的代码及输出中可以看到,输出的日志与我们传入的字符串有一些差异。
比如logging.info('这是一条info日志')
的输出是INFO:root:这是一条info日志
。
其中INFO
和root
是默认输出的内容,可通过设置格式来修改日志格式和内容。
INFO:日志等级
root:https://docs.python.org/3/howto/logging.html#advanced-logging-tutorial
https://docs.python.org/zh-cn/3/library/logging.html#logrecord-attributes
可以通过格式化进行日志输出。
常用的有:
args
:不需要用户进行格式化。合并到 msg 以产生 message 的包含参数的元组,或是其中的值将被用于合并的字典(当只有一个参数且其类型为字典时)。msg
:不需要用户进行格式化。在原始日志记录调用中传入的格式字符串。 与 args 合并以产生 message,或是一个任意对象message
:记入日志的消息,即 msg % args 的结果。asctime
:表示该条日志记录是何时被创建的。‘2022-03-31 14:22:41,962’ (逗号之后的数字为时间的毫秒部分)filename
:pathname 的文件名部分。funcName
:函数名包括调用日志记录。levelname
:消息文本记录级别(‘DEBUG’,‘INFO’,‘WARNING’,‘ERROR’,‘CRITICAL’)。lineno
:发出日志记录调用所在的源行号(如果可用)。name
:用于记录调用的日志记录器名称。import logging
FORMAT = '%(asctime)s %(filename)s %(funcName)s %(levelname)s %(lineno)s %(message)s '
logging.basicConfig(filename=None, filemode='a', format= FORMAT, level=logging.DEBUG)
logging.debug('这是一条debug日志')
logging.info('这是一条info日志')
logging.warning('这是一条warning日志')
logging.error('这是一条error日志')
def foo():
logging.info('这是一条来自foo函数的info日志')
foo()
#2022-03-31 16:22:17,561 a0.py DEBUG 8 这是一条debug日志
#2022-03-31 16:22:17,561 a0.py INFO 9 这是一条info日志
#2022-03-31 16:22:17,561 a0.py WARNING 10 这是一条warning日志
#2022-03-31 16:22:17,562 a0.py ERROR 11 这是一条error日志
#2022-03-31 16:22:17,562 a0.py foo INFO 14 这是一条来自foo函数的info日志
FORMAT
可以参考上面的变量按需求组织输出格式。
可通过传入一个字典,按找需求输出日志。有时候会需要使用到多个不同的自定义格式变量,可以传入一个字典,其中的key对应自定义变量名。
import logging
FORMAT = '%(asctime)s epochs:%(epochs)s lr:%(lr)s loss:%(loss)s %(message)s '
logging.basicConfig(filename=None, filemode='a', format= FORMAT, level=logging.DEBUG)
d = {
'epochs': '30/10000',
'lr': 1e-5,
'loss': 0.0024788384325802326
}
logging.info('自定义', extra=d)
#2022-03-31 16:34:46,564 epochs:30/10000 lr:1e-05 loss:0.0024788384325802326 自定义
# custom_logger.py
import logging
def set_logging(name=None, level=logging.WARNING, verbose=True):
# 设置日志等级并返回实例。可同时保存到文件和打印到控制台
logger = logging.getLogger(name)
logger.setLevel(level=level)
FORMAT = '%(asctime)s [%(name)s] %(filename)s[line:%(lineno)d] %(levelname)s: %(message)s'
formatter = logging.Formatter(FORMAT)
# 保存到文件
fh = logging.FileHandler(filename='debug/test.txt', encoding='utf-8', mode='a') # encoding避免中文保存到文件出现乱码
fh.setFormatter(formatter)
logger.addHandler(fh)
if verbose:
# 打印到控制台
sh = logging.StreamHandler()
sh.setFormatter(formatter)
logger.addHandler(sh)
return logger
LOGGER = set_logging(name='test', level=logging.INFO, verbose=True)
if __name__ == '__main__':
LOGGER.info('这是一条日志')
# 2022-04-30 13:47:24,663 [test] custom_logger.py[line:29] INFO: 这是一条日志
如果内容对你有帮助,或者觉得写的不错
️欢迎点赞 收藏 ⭐留言
有问题,请在评论区留言