日志让我们可以监测程序运行的状态。当然,很多时候用print也可以完成,但是学过会发现,用专门的日志模块会更加省力。

       

      默认情况下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}: ***')

python logging 异常详细信息 python logging info_配置文件

这里的logging.info就print的功能,输出日志信息。前面初始化了日志输出的格式,后面代码中只需要写内容(对应message),时间等信息都会自动带上,这就是loggingprint方便的地方。

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信息')