日志让我们可以监测程序运行的状态。当然,很多时候用
默认情况下python的logging模块将日志打印到了标准输出(屏幕)中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET)
import logging logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s') for i in range(10): logging.info(f'iteration {i}: ***')
这里的
logging.info就
是logging
比logging.getLogger(name)
logging.getLogger(name)获取logger对象,如果不指定name则返回root对象,多次使用相同的name调用getLogger方法返回同一个logger对象。
logging信息输出到文件中
import logging
logging.basicConfig(
filename="log.txt",
level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s')
for i in range(10):
logging.info(f'iteration {i}: ***')
这样就会只输出到文件中,而且内容是在后面追加
logging信息输出到屏幕+文件中
import logging
import sys
logging.basicConfig(
filename="log.txt",
level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s')
logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))
for i in range(10):
logging.info(f'iteration {i}: ***')
但是这种写法遇到过不起作用的情况,像导入MONAI库的时候
下面这种写法更有用
import logging
my_logger = logging.getLogger('my_logger')
my_logger.setLevel(logging.INFO)
# 创建一个将日志写入文件的处理器,并将其附加到 my_logger 记录器上
file_handler = logging.FileHandler('my_log_file.txt')
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(
logging.Formatter('%(asctime)s %(levelname)s %(message)s')
)
my_logger.addHandler(file_handler)
# 输出一些日志消息
my_logger.debug('Debug message')
my_logger.info('Info message')
my_logger.warning('Warning message')
my_logger.error('Error message')
my_logger.critical('Critical message')
运行的时候python -u lian.py
logging输出配置文件内容
config = parse_args() logger.info(json.dumps(config, indent=2))
logging模块不工作
在 PyTorch 中,如果在导入某些包之后
logging
模块停止工作,这通常是因为其他包修改了logging
模块的配置或者覆盖了logging
模块的配置。像我遇到过导入MONAI的包之后logging就不起作用了
解决方法是 给logging.basicConfig的force参数设为True,就可以了。但是必须要python3.8才行
logging.basicConfig( filename="log.txt", level=logging.INFO, format='[%(asctime)s.%(msecs)03d] %(message)s', datefmt='%H:%M:%S', force=True, )
huggingface的transformers库中也有logging模块,注意
一个常见的问题是 PyTorch 自带的 CUDA 库(
torch.cuda
)可能会覆盖logging
模块的配置。这是因为 CUDA 使用了自己的logging
配置。在这种情况下,可以使用以下代码来恢复
logging
模块的配置:import logging import torch # 获取 CUDA 的 logger cuda_logger = logging.getLogger('torch.cuda') # 禁用 CUDA 的 logger cuda_logger.disabled = True # 恢复 logging 模块的配置 logging.basicConfig(level=logging.DEBUG)
在这个示例中,我们首先获取了 CUDA 的 logger,并将其禁用。然后,我们通过
basicConfig()
函数恢复了logging
模块的配置。如果你的代码中有其他的包也影响了
logging
模块的配置,可以使用类似的方法来恢复配置。为什么很多程序都是logging.getLogger(__name__)
logging.getLogger(__name__)
是一种常用的获取 logger 对象的方式,它的作用是创建一个以模块名为名称的 logger 对象。这样,每个模块都会有自己独立的 logger 对象,用于记录该模块中发生的事件和错误信息。这种方式可以避免在不同模块中使用同一个 logger 对象时发生名称冲突的问题。当一个项目比较大的时候,不同的文件中都要用到logging,可以考虑将其封装为一个类来使用
#! /usr/bin/env python
#coding=gbk
import logging,os
class Logger:
def __init__(self, path,clevel = logging.DEBUG,Flevel = logging.DEBUG):
self.logger = logging.getLogger(path)
self.logger.setLevel(logging.DEBUG)
fmt = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S')
#设置CMD日志
sh = logging.StreamHandler()
sh.setFormatter(fmt)
sh.setLevel(clevel)
#设置文件日志
fh = logging.FileHandler(path)
fh.setFormatter(fmt)
fh.setLevel(Flevel)
self.logger.addHandler(sh)
self.logger.addHandler(fh)
def debug(self,message):
self.logger.debug(message)
def info(self,message):
self.logger.info(message)
def war(self,message):
self.logger.warn(message)
def error(self,message):
self.logger.error(message)
def cri(self,message):
self.logger.critical(message)
if __name__ =='__main__':
logyyx = Logger('yyx.log',logging.ERROR,logging.DEBUG)
logyyx.debug('一个debug信息')
logyyx.info('一个info信息')
logyyx.war('一个warning信息')
logyyx.error('一个error信息')
logyyx.cri('一个致命critical信息')