日志记录logging

news2024/9/20 12:41:45

文章目录

    • 1. logging基础使用
      • 1.1 日志的6个级别
      • 1.2 logging.basicConfig
      • 1.3 案例
    • 2. logging的高级应用
      • 2.1 记录器Logger
      • 2.2 处理器- Handler
      • 2.3 格式器- Formatter
      • 2.4 创建关联
      • 2.4 案例
    • 3.在项目中的应用
      • 3.1 定义全局使用的logger对象
      • 3.2 使用案例
    • 参考

1. logging基础使用

1.1 日志的6个级别

序号级别级别数值使用情况
1NOTEST/不记录任何日志信息
2DEBUG10用于记录开发过程中的细节信息,例如函数调用,变量值等
3INFO20用于记录程序正常运行过程中的一般信息
4WARNING30用于记录可能导致问题的潜在问题,例如语法警告、网络连接中断等
5ERROR40用于记录程序运行过程中发生的错误,例如函数调用失败,异常发生等
6CRITICAL50用于记录严重的错误,例如程序奔溃等

级别从低到高依次为: NOTEST < DEBUG < INFO < WARNING < ERROR < CRITICAL, 默认为WARNING级别, 默认情况下日志打印只显示大于等于 WARNING 级别的日志

1.2 logging.basicConfig

通过logging.basicConfig函数对日志的输出格式及方式做相关配置

logging.basicConfig(
    level = logging.INFO,
    format = '%(asctime)s %(name) |%(pathname)s line:(lineno)d'
    datefmt = "%Y-%m-%d %H:%M:%S",
    filename ='demo.log',
    filemode = 'w'
)
  • level: 指定打印日志的级别,debug,info,warning,error,critical
  • format: 日志输出相关格式

1.3 案例

案例1:显示消息日期

import logging
# 显示消息时间
logging.basicConfig(format='%(asctime)s %(message)s')
logging.warning('is when this event was logged.')

logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('is when this event was logged.')
2019-10-16 18:57:45,988 is when this event was logged.
2019-10-16 18:57:45,988 is when this event was logged.
  • 案例2:将日志信息记录到文件
# 日志信息记录到文件
logging.basicConfig(filename='F:/example.log', level=logging.DEBUG)

logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')

在相应的路径下会有 example.log 日志文件,内容如下:

DEBUG:root:This message should go to the log file
INFO:root:So should this
WARNING:root:And this, too

2. logging的高级应用

logging 采用了模块化设计,主要由四个部分组成:

  • (1) Loggers: 日志记录器,提供程序直接调用的接口
  • (2) Handers: 日志处理器,将记录的日志发送到指定的位置(终端打印or 保存到文件)
  • (3)Filters: 日志过滤器,提供更细粒度控制,决定哪些日志被输出
  • (4) Formatters: 日志格式器,用于控制信息的输出格式

2.1 记录器Logger

Logger 持有日志记录器的方法,日志记录器不直接实例化,而是通过模块级函数logging.getlogger (name)来实例化

  • 应用程序代码能直接调用日志接口。
  • Logger最常用的操作有两类:配置和发送日志消息
  • 初始化 logger = logging.getLogger("endlesscode")获取 logger 对象,getLogger() 方法后面最好加上所要日志记录的模块名字,配置文件和打印日志格式中的%(name)s对应的是这里的模块名字,如果不指定name则返回root对象。
  • logger.setLevel(logging.DEBUG),Logging 中有 NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL这几种级别,日志会记录设置级别以上的日志
  • 多次使用相同的name调用 getLogger 方法返回同一个 looger 对象;
# 实例化一个记录器,并将记录器的名字设为 `trainning_log`
logger = logging.getlogger (name)(name = 'training_log')

#设置 logger的日志级别
logger.setLevel(logging.INFO)

如果 logging.getlogger 不设置参数name的话,默认记录器名字为root

2.2 处理器- Handler

Handler 处理器类型有很多种,比较常用的有三个,StreamHandlerFileHandler,NullHandler

  • 创建一个handler, 该handler往console(终端)打印输出
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.DEBUG)
  • 创建一个handler, 该handle往文件中打印输出
fileHandler = logging.FileHander(filename ='demo.log')

2.3 格式器- Formatter

使用Formatter对象设置日志信息最后的规则、结构和内容,默认的时间格式为%Y-%m-%d %H:%M:%S

  • 创建方法:
formatter = logging.Formatter(fmt=None, datefmt=None)

其中,fmt消息的格式化字符串datefmt日期字符串。如果不指明 fmt,将使用'%(message)s'。如果不指明 datefmt,将使用 ISO8601 日期格式。

# 创建一个标准版日志打印格式
standard_formatter = logging.setFormatter('%(asctime)s %(name)s [%(pathname)s line:(lineno)d %(levelname)s %(message)s]')

# 创建一个简单版的日志打印格式
simple_formatter = logging.setFormatter('%(levelname)s %(message)s')

2.4 创建关联

在这里插入图片描述
我们在创建好Logger对象,Handler对象以及Formatter对象之后,我们需要绑定他们之间的关系。

  • 首先为Handler设置Formatter, 然后将Handler绑定到logger上
#创建一个handler, 该handler往`console`(终端)打印输出
consoleHandler = logging.StreamHandler()
#创建一个handler, 该handle往`文件`中打印输出
fileHandler = logging.FileHander(filename ='demo.log')

# 让consoleHander,使用标注版日志打印输出
consoleHandler.setFormatter(standard_formatter)
fileHandler.setFormatter(simple_formatter) 

# 给logger绑定上consoleHandler和fileHandler
logger.addHandler(console_handle)
logger.addHandler(file_handle)

2.4 案例

import logging

#------------------1. 实例化 logger -------------------#
# 实例化一个记录器,使用默认记录器名称‘root’,并将日志级别设置为info
logger = logging.getLogger()
logger.setLevel(logging.Debug)

#-----------------2. 定义 Handler --------------------#
# 创建一个往控制台打印输出的Handler,日志级别为 debug
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)

# 再创建一个往文件中打印输出的handler,默认使用logger同样的日志级别
file_handler = logging.FileHandler(filename = 'demo.log',mode ='a')

#---------------3. 定义打印格式Formatter--------------#
# 创建一个标准版日志打印格式
standard_formatter = logging.setFormatter('%(asctime)s %(name)s [%(pathname)s line:(lineno)d %(levelname)s %(message)s]')

# 创建一个简单版日志打印格式
simple_formatter = logging.Formatter('%(levelname)s %(message)s')
#---------------------3. 定义过滤器------------------#
#fit = logging.Filter()
#--------------------4. 绑定 -----------------------#
# 让consoleHandler使用标准版日志打印格式
console_handler.setFormatter(standard_formatter)

# 让fileHandler使用简版的日志打印格式
file_handler.setFormatter(simple_formmatter)

# 给logger 绑定上consoleHandle和fileHandler
logger.addHandler(console_handler)
logger.addHandler(file_handler)

#----------------------5. 打印--------------------#
logger.debug('调试日志')
logger.info('消息日志')
logger.warning('警告日志')
logger.error('错误日志')
logger.critical('严重错误日志')
  • 运行程序,在终端打印出了日志信息,同样在文件demo.log也保存了日志信息

补充: 接下来,补充下Filter相关的知识

  • 比如,我们定义logger的名字为training.loss.log
logger = logging.getLogger('training.loss.log')
  • 接下来给过滤器Filter一个字符串参数如果这个字符串是logger的名字的前缀,那么日志就不会被过滤,可以正常打印出来;如果指定Filter的字符串参数和logger名字的前缀不匹配,那么这个logger就打印不出来日志`
fit = logging.Filter('training.loss') #可以打印出日志,与logger名前缀想匹配
fit = logging.Filter('training.accuracy') #打印不出日志,与logger名前缀不匹配

最后需要将过滤器绑定logger或者handler,如果绑定logger则针对所有handler都使用该过滤器,如果绑定某一个handler则该handler使用绑定的过滤器filter

logger.addFilter(fit)
#或者
console_handler.addFilter(fit)

3.在项目中的应用

首先在一个文件中定义logger对象,在项目中任何需要使用的地方,直接引用该logger,利用logger就可以打印输出相关日志信息,信息主要是输出到控制台(console)显示使用。

3.1 定义全局使用的logger对象

比如在general.py中定义logger对象LOGGER

import logging
import os
import platform
import sys

RANK = int(os.getenv("RANK", -1))
LOGGING_NAME = "ultralytics"
MACOS, LINUX, WINDOWS = (platform.system() == x for x in ["Darwin", "Linux", "Windows"])

def set_logging(name=LOGGING_NAME, verbose=True):
    """Sets up logging for the given name with UTF-8 encoding support."""
    level = logging.INFO if verbose and RANK in {-1, 0} else logging.ERROR  # rank in world for Multi-GPU trainings

    # Configure the console (stdout) encoding to UTF-8
    formatter = logging.Formatter("%(message)s")  # Default formatter
    if WINDOWS and sys.stdout.encoding != "utf-8":
        try:
            if hasattr(sys.stdout, "reconfigure"):
                sys.stdout.reconfigure(encoding="utf-8")
            elif hasattr(sys.stdout, "buffer"):
                import io

                sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")
            else:
                sys.stdout.encoding = "utf-8"
        except Exception as e:
            print(f"Creating custom formatter for non UTF-8 environments due to {e}")

            class CustomFormatter(logging.Formatter):
                def format(self, record):
                    """Sets up logging with UTF-8 encoding and configurable verbosity."""
                    return emojis(super().format(record))

            formatter = CustomFormatter("%(message)s")  # Use CustomFormatter to eliminate UTF-8 output as last recourse

    # Create and configure the StreamHandler
    stream_handler = logging.StreamHandler(sys.stdout)
    stream_handler.setFormatter(formatter)
    stream_handler.setLevel(level)

    logger = logging.getLogger(name)
    logger.setLevel(level)
    logger.addHandler(stream_handler)
    logger.propagate = False
    return logger


# Set logger
LOGGER = set_logging(LOGGING_NAME, verbose=VERBOSE)  # define globally (used in train.py, val.py, predict.py, etc.)
  • 首先通过set_logging() 设置日志级别(在主进程中使用info级别,其他进程error级别),通过StreamHandler将信息打印到控制台,并绑定输出的信息样式Formatter,然后将handler绑定到logger对象上
  • 定义的LOGGER 可以全局使用,包括train.py, val.py, predict.py等等中使用,使用时候从general中导入LOGGER即可

3.2 使用案例

在使用日志打印信息前,首先需要在使用的文件中,比如train.py中导入LOGGER,比如:

from utils.general import LOGGER

其中yolov8项目导入LOGGER

from ultralytics.utils import LOGGER,
  • 案例1
 if install and AUTOINSTALL:  # check environment variable
     n = len(pkgs)  # number of packages updates
     LOGGER.info(f"{prefix} Ultralytics requirement{'s' * (n > 1)} {pkgs} not found, attempting AutoUpdate...")
     try:
         t = time.time()
         assert is_online(), "AutoUpdate skipped (offline)"
         LOGGER.info(subprocess.check_output(f"pip install --no-cache {s} {cmds}", shell=True).decode())
         dt = time.time() - t
         LOGGER.info(
             f"{prefix} AutoUpdate success ✅ {dt:.1f}s, installed {n} package{'s' * (n > 1)}: {pkgs}\n"
             f"{prefix} ⚠️ {colorstr('bold', 'Restart runtime or rerun command for updates to take effect')}\n"
         )
     except Exception as e:
         LOGGER.warning(f"{prefix}{e}")
         return False
 else:
     return False
  • 案例2
def on_pretrain_routine_end(trainer):
    global mlflow

    uri = os.environ.get("MLFLOW_TRACKING_URI") or str(RUNS_DIR / "mlflow")
    LOGGER.debug(f"{PREFIX} tracking uri: {uri}")
    mlflow.set_tracking_uri(uri)

    # Set experiment and run names
    experiment_name = os.environ.get("MLFLOW_EXPERIMENT_NAME") or trainer.args.project or "/Shared/YOLOv8"
    run_name = os.environ.get("MLFLOW_RUN") or trainer.args.name
    mlflow.set_experiment(experiment_name)

    mlflow.autolog()
    try:
        active_run = mlflow.active_run() or mlflow.start_run(run_name=run_name)
        LOGGER.info(f"{PREFIX}logging run_id({active_run.info.run_id}) to {uri}")
        if Path(uri).is_dir():
            LOGGER.info(f"{PREFIX}view at http://127.0.0.1:5000 with 'mlflow server --backend-store-uri {uri}'")
        LOGGER.info(f"{PREFIX}disable with 'yolo settings mlflow=False'")
        mlflow.log_params(dict(trainer.args))
    except Exception as e:
        LOGGER.warning(f"{PREFIX}WARNING ⚠️ Failed to initialize: {e}\n" f"{PREFIX}WARNING ⚠️ Not tracking this run")
  • 案例3
def on_train_end(trainer):
    """Upload final model and metrics to Ultralytics HUB at the end of training."""
    session = getattr(trainer, "hub_session", None)
    if session:
        # Upload final model and metrics with exponential standoff
        LOGGER.info(f"{PREFIX}Syncing final model...")
        session.upload_model(
            trainer.epoch,
            trainer.best,
            map=trainer.metrics.get("metrics/mAP50-95(B)", 0),
            final=True,
        )
        session.alive = False  # stop heartbeats
        LOGGER.info(f"{PREFIX}Done ✅\n" f"{PREFIX}View model at {session.model_url} 🚀")
  • 案例4
def on_pretrain_routine_start(trainer):
    """Runs at start of pretraining routine; initializes and connects/ logs task to ClearML."""
    try:
        if task := Task.current_task():
            # Make sure the automatic pytorch and matplotlib bindings are disabled!
            # We are logging these plots and model files manually in the integration
            PatchPyTorchModelIO.update_current_task(None)
            PatchedMatplotlib.update_current_task(None)
        else:
            task = Task.init(
                project_name=trainer.args.project or "YOLOv8",
                task_name=trainer.args.name,
                tags=["YOLOv8"],
                output_uri=True,
                reuse_last_task_id=False,
                auto_connect_frameworks={"pytorch": False, "matplotlib": False},
            )
            LOGGER.warning(
                "ClearML Initialized a new task. If you want to run remotely, "
                "please add clearml-init and connect your arguments before initializing YOLO."
            )
        task.connect(vars(trainer.args), name="General")
    except Exception as e:
        LOGGER.warning(f"WARNING ⚠️ ClearML installed but not initialized correctly, not logging this run. {e}")
  • 案例5
def check_cache_ram(self, safety_margin=0.5):
      """Check image caching requirements vs available memory."""
      b, gb = 0, 1 << 30  # bytes of cached images, bytes per gigabytes
      n = min(self.ni, 30)  # extrapolate from 30 random images
      for _ in range(n):
          im = cv2.imread(random.choice(self.im_files))  # sample image
          ratio = self.imgsz / max(im.shape[0], im.shape[1])  # max(h, w)  # ratio
          b += im.nbytes * ratio**2
      mem_required = b * self.ni / n * (1 + safety_margin)  # GB required to cache dataset into RAM
      mem = psutil.virtual_memory()
      cache = mem_required < mem.available  # to cache or not to cache, that is the question
      if not cache:
          LOGGER.info(
              f'{self.prefix}{mem_required / gb:.1f}GB RAM required to cache images '
              f'with {int(safety_margin * 100)}% safety margin but only '
              f'{mem.available / gb:.1f}/{mem.total / gb:.1f}GB available, '
              f"{'caching images ✅' if cache else 'not caching images ⚠️'}"
          )
      return cache

总结
利用logger日志输出,可以替换print, 这样的话,在不需要日志信息输出时,可以通过调整日志级别,有选择的打印信息。

参考

  1. https://zhuanlan.zhihu.com/p/425678081
  2. https://github.dev/ultralytics/ultralytics

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1398934.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Wpf 使用 Prism 实战开发Day13

配置 AutoMapper 关系映射 在上一节 ToDoController 控制器&#xff0c;或 IToDoService 服务接口中&#xff0c;方法的传参都是直接传的实体类。但在实际开发过程中&#xff0c;这样是不允许的。标准且规范的做法是&#xff0c;定义一个数据传输层&#xff0c;即Dto层。 一.在…

荣誉艾尔迪亚人的题解

目录 原题描述&#xff1a; 题目背景 题目描述 输入格式 输出格式 样例 Input 1 Output 1 Input 2 Output 2 数据范围&#xff1a; 样例解释 主要思路&#xff1a; 代码code&#xff1a; 原题描述&#xff1a; 时间限制: 1000ms 空间限制: 65536kb 题目背景 ​…

GPT应用_PrivateGPT

项目地址&#xff1a;https://github.com/imartinez/privateGPT 1 功能 1.1 整体功能&#xff0c;想解决什么问题 搭建完整的 RAG 系统&#xff0c;与 FastGPT 相比&#xff0c;界面比较简单。但是底层支持比较丰富&#xff0c;可用于知识库的完全本地部署&#xff0c;包含大…

如何选择工程师职称申报的专业?

选择适合自己的职称评定专业&#xff0c;需从官方申报范围、公示名单中寻找答案&#xff0c;并选择适合自己的评审方式。需具备一定的工作年限、学历要求和充分证明自己能力水平的材料&#xff0c;方可获得职称资格。 在职称评定之路上&#xff0c;选择一个适合自己的专业&…

论文阅读笔记AI篇 —— Transformer模型理论+实战 (四)

论文阅读笔记AI篇 —— Transformer模型理论实战 &#xff08;四&#xff09; 一、理论1.1 理论研读1.2 什么是AI Agent? 二、实战2.1 先导知识2.1.1 tensor的创建与使用2.1.2 PyTorch的模块2.1.2.1 torch.nn.Module类的继承与使用2.1.2.2 torch.nn.Linear类 2.2 Transformer代…

设计模式--组合模式

缘起 某日&#xff0c;小明公司最近接到一个办公管理系统的项目&#xff0c;并且在每个城市都有分部。这属于是很常见的OA系统&#xff0c;只要前期将需求分析完善好&#xff0c;中后期开发维护是不难的。 然而&#xff0c;总部公司使用后觉得很OK&#xff0c;想要其他城市的…

【Proxy】Windows 10 的 Command Line Proxy 设置

【Proxy】Windows 10 的 Command Line Proxy 设置 1 本机环境2 PowerShell3 CMD 1 本机环境 Windows 10v2rayN 在 v2rayN 界面下方可以看到 socks 和 http 的端口号&#xff0c;分别为 10808 和 10809 2 PowerShell 每次打开新窗口&#xff0c;执行下面的命令 $env:HTTP_…

无刷电机行业调研:市场销售规模达到537亿元

无刷直流电机(BLDC&#xff1a;Brushless Direct Current Motor)&#xff0c;也被称为电子换向电机(ECM或EC电机)或同步直流电机&#xff0c;是一种使用直流电(DC)电源的同步电机。无刷直流电机实质上为采用直流电源输入&#xff0c;并用逆变器变为三相交流电源&#xff0c;带位…

GitHub图床TyporaPicGo相关配置

本文作者&#xff1a; slience_me 文章目录 GitHub图床&Typora&PicGo相关配置1. Github配置2. picGo配置3. Typora配置 GitHub图床&Typora&PicGo相关配置 关于Typora旧版的百度网盘下载路径 链接&#xff1a;https://pan.baidu.com/s/12mq-dMqWnRRoreGo4MTbKg?…

三国游戏(寒假每日一题+贪心、枚举)

题目 小蓝正在玩一款游戏。 游戏中魏蜀吴三个国家各自拥有一定数量的士兵 X,Y,Z&#xff08;一开始可以认为都为 0&#xff09;。 游戏有 n 个可能会发生的事件&#xff0c;每个事件之间相互独立且最多只会发生一次&#xff0c;当第 i个事件发生时会分别让 X,Y,Z 增加 Ai,Bi…

零基础学Python(2)— 安装Python开发工具之PyCharm

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。PyCharm是由JetBrains公司开发的一款Python开发工具。在Windows、Mac OS和Linux操作系统中都可以使用。它具有语法高亮显示、Project&#xff08;项目&#xff09;管理代码跳转、智能提示、自动完成、调试、单元测试和版本…

关于SQL-case when最全面的学习笔记

case when 推荐学习书籍&#xff1a;1、SQL基础教程 6-32、SQL进阶教程 1-1 case when 是SQL语法中提供的标准的条件分支。 条件分支在MYSQL中即为IF函数&#xff0c;不同的数据库都会提供自己的一些函数&#xff0c;但是CASE WHEN 更加通用。 CASE语句的两种写法 1、搜索CASE…

Ubuntu使用docker-compose安装mysql8或mysql5.7

ubuntu环境搭建专栏&#x1f517;点击跳转 Ubuntu系统环境搭建&#xff08;十四&#xff09;——使用docker-compose安装mysql8或mysql5.7 文章目录 Ubuntu系统环境搭建&#xff08;十四&#xff09;——使用docker-compose安装mysql8或mysql5.7MySQL81.新建文件夹2.创建docke…

在码云(gitee)里面提交代码进行保存步骤(自留笔记)

一些需要用到的软件需要自行下载 视频可观看https://www.bilibili.com/video/BV1hf4y1W7yT/ 步骤&#xff1a; 1.打开码云&#xff0c;点击加号&#xff0c;创建仓库 2.此处我的仓库选择私有&#xff0c;也可以选择开源&#xff0c;选择开源时&#xff0c;注意把弹出来的选项全…

「Kafka」Broker篇

「Kafka」Broker篇 主要讲解的是在 Kafka 中是怎么存储数据的&#xff0c;以及 Kafka 和 Zookeeper 之间如何进行数据沟通的。 Kafka Broker 总体工作流程 Zookeeper 存储的 Kafka 信息 启动 Zookeeper 客户端&#xff1a; [atguiguhadoop102 zookeeper-3.5.7]$ bin/zkCli.sh通…

【JavaEE】_网络编程基础

目录 1. 网络编程基础 1.1 网络编程定义 1.2 网络编程中的基本概念 1.2.1 API 1.2.2.发送端和接收端 1.2.3 请求和响应 1.2.4 客户端和服务端 2. Socket 套接字 2.1 概念 2.2 分类 3. UDP数据报套接字编程 3.1 DatagramSocket API 3.1.1 含义 3.1.2 构造方法 3…

全景摄像机行业分析:市场规模不可限量

早期的全景相机行业竞争格局较为多元。近年来随着行业技术不断成熟&#xff0c;市场的竞争格局由多家参与逐步向头部企业聚拢&#xff0c;国内企业凭借图像处理技术优势在全景相机行业中逐步抢占市场份额。 全景摄像机&#xff0c;是可以独立实现大范围无死角监控的摄像机。 一…

OpenVINS学习7——评估工具的简单使用

前言 OpenVINS自带评估工具&#xff0c;这里记录一下使用方法&#xff0c;我是以VIRAL数据集为例&#xff0c;但是目前仍然有问题&#xff0c;发现误差很大&#xff0c;我还没搞明白哪里出了问题。 工具介绍 主要参考 https://docs.openvins.com/eval-error.html https://bl…

ELK 日志分析系统

目录 一、日志管理方案 二、完整日志系统基本特征 三、ELK 简介 ELK组件&#xff1a; 1、ElasticSearch 2、Logstash 3、Kibana 可以添加的其它组件&#xff1a; 1、Filebeat 2、缓存/消息队列&#xff08;redis、kafka、RabbitMQ等&#xff09; 3、Fluentd 三、ELK …

作业-数组计数法

目录 数字出现次数 题目描述 输入 输出 输入复制 输出复制 求n个数中每个数出现的次数 题目描述 输入 输出 输入复制 输出复制 声音识别 题目描述 输入 输出 输入复制 输出复制 选班委 题目描述 输入 输出 输入复制 输出复制 数字出现次数 题目描述 …