日志记录logging

文章目录

    • 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】配置dns主从服务器,能够实现正常的正反向解析

​​​​​​1、首先&#xff0c;在主服务器上配置DNS解析器。打开配置文件/etc/named.conf&#xff0c;添加以下内容&#xff1a; zone"example.com" IN {type master;file "example.com.zone";allow-transfer { slave_ip_address: }; };zone"xx.16…

减少 LLM 幻觉方法--CoVe

​来自于 Meta AI&#xff0c;原文链接&#xff1a;https://arxiv.org/abs/2309.11495 LLM 经常遇到的主要问题就是幻觉&#xff0c;减少幻觉的方法大致可分为三类&#xff1a;训练时校正、生成时校正和通过增强&#xff08;使用工具&#xff09;进行校正。 在训练时校正的方法…

burp靶场--文件上传

burp靶场–文件上传 https://portswigger.net/web-security/file-upload/lab-file-upload-remote-code-execution-via-web-shell-upload 1.文件上传 1、原理&#xff1a;文件上传漏洞是指Web服务器允许用户将文件上传到其文件系统&#xff0c;而不充分验证文件的名称、类型、…

SpringMVC环境搭配

概述 Spring MVC是Spring Framework提供的Web组件&#xff0c;全称是Spring Web MVC,是目前主流的实现MVC设计模式的框架&#xff0c;提供前端路由映射、视图解析等功能 mvc是什么 MVC是一种软件架构思想&#xff0c;把软件按照模型&#xff0c;视图&#xff0c;控制器来划分…

linux基础学习(5):yum

yum是为了解决rpm包安装依赖性而产生的一种安装工具 1.yum源 1.1配置文件位置 yum源的配置文件在/etc/yum.repos.d/中 *Base源是网络yum源&#xff0c;也就是需要联网才能使用的yum源。默认情况下&#xff0c;系统会使用Base源 *Media源是光盘yum源&#xff0c;是本地yum源…

如何防止你的 Goroutine 泄露 Part2

文章目录 简述NumGoroutine演示案例pprofruntime/pprofhttp/net/pprof gopsLeak Test总结参考资料 上篇 文章说到&#xff0c;防止 goroutine 泄露可从两个角度出发&#xff0c;分别是代码层面的预防与运行层面的监控检测。今天&#xff0c;我们来谈第二点。 简述 前文已经介…

GPT应用开发:编写插件获取实时天气信息

欢迎阅读本系列文章&#xff01;我将带你一起探索如何利用OpenAI API开发GPT应用。无论你是编程新手还是资深开发者&#xff0c;都能在这里获得灵感和收获。 本文&#xff0c;我们将继续展示聊天API中插件的使用方法&#xff0c;让你能够轻松驾驭这个强大的工具。 插件运行效…

【计算机网络】2、传输介质、通信方向、通信方式、交换方式、IP地址表示、子网划分

文章目录 传输介质双绞线无屏蔽双绞线UTP屏蔽双绞线STP 网线光纤多模光纤MMF单模光纤SMF 无线信道无线电波红外光波 通信方向单工半双工全双工 通信方式异步传输同步传输串行传输并行传输 交换方式电路交换报文交换分组交换 IP地址表示IP地址的定义IP地址的分类无分类编址特殊I…

6.STEP格式模型的AP214和AP203格式有什么区别?

STEP&#xff1a;(Standard for the Exchange of Product Model Data&#xff0d;产品模型数据交互规范)&#xff0c;是一个比较全面的ISO标准 (ISO10303)&#xff0c;该标准描述了如何表示和交换数字产品信息。 其实就是3D文件的一个通用格式&#xff0c;每个3D设计软件都支持…

基于深度学习的车牌识别(YOLOv5和CNN)

基于深度学习的车牌识别(YOLOv5和CNN&#xff09; 目录 一、综述 二、车牌检测 一、综述 本篇文章是面向的是小白&#xff0c;想要学习深度学习上的应用&#xff0c;本文中目前应用了YOLO v5和CNN来对车牌进行处理&#xff0c;最终形成一个完整的车牌信息记录&#xff0c;…

强网杯2023 crypto

speed up 当时看到这个题目 也是觉得易懂 并且可以解出来的 但是数字实在是过大了兄弟 题目意思是计算2^27的阶乘,并获取得到每一位数的数字之和,flag即为该数字的sha256编码 2^27为134217728 gmpy2包是支持大数运算的,故利用其fac方法进行尝试,在等待一段时间后可以得到对…

第二次作业

1.基于域名[www.openlab.com](http://www.openlab.com)可以访问网站内容为 welcome to openlab!!! 创建文件 编辑文件 创建目录 添加内容 重启系统 更改host文件 在host追加域名 最后在网页查看及可 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网…

flutter获取地理定位:geolocator依赖详细用法

本文使用geolocator插件实现app物理定位功能。 该插件的主要功能有&#xff1a; 获取最后已知位置&#xff1b;获取设备当前位置&#xff1b;获取连续的位置更新&#xff1b;检查设备是否启用了定位服务&#xff1b;计算两个地理坐标之间的距离&#xff08;米&#xff09;&am…

数据结构——排序

前言&#xff1a;哈喽小伙伴们好久不见&#xff0c;也是顺利的考完试迎来了寒假。众所周知&#xff0c;不怕同学是学霸&#xff0c;就怕学霸放寒假&#xff0c;假期身为弯道超车的最佳时间&#xff0c;我们定然是不能懒散的度过。 今天我们就一起来学习数据结构初阶的终章——…

眼镜用超声波清洗机好不好?洗眼镜比较好用的超声波清洗机推荐

眼镜是我们日常生活中必不可少的用品&#xff0c;它不仅能帮助我们矫正视力&#xff0c;更是我们与外界进行交流的重要工具。然而&#xff0c;随着眼镜的长时间佩戴&#xff0c;眼镜表面容易积累灰尘、污垢和细菌&#xff0c;这不仅影响了我们的视野&#xff0c;也可能对眼睛健…

Docker(一)简介和基本概念:什么是 Docker?用它会带来什么样的好处?

作者主页&#xff1a; 正函数的个人主页 文章收录专栏&#xff1a; Docker 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01; 一、简介 本章将带领你进入 Docker 的世界。 什么是 Docker&#xff1f; 用它会带来什么样的好处&#xff1f; 好吧&#xff0c;让我们带…

Python连接数据库的梳理

我们通常用的数据库类型主要有关系型数据库&#xff0c;非关系型数据库等&#xff0c;其中关系型数据库主要有Microsoft SQL Server ,MySQL,Oracle&#xff0c;SQLite等&#xff0c;常用的非关系型数据库包括Redis、DynamoDB&#xff0c;MongoDB等 ​​​​​​​ 一 关系型…

hdu 3709 Balanced Number

Balanced Number 题意 定义一个非负整数在第 p p p 位为 p i v o t pivot pivot 的权重为&#xff1a;这个数位的值 \times 这个数位到 p i v o t pivot pivot 的距离 之和。如果在 p i v o t pivot pivot 左边的权重等于在 p i v o t pivot pivot 右边的权重&#xf…

uni-app小程序:文件下载打开文件方法苹果安卓都适用

api: const filetype e.substr(e.lastIndexOf(.)1)//获取文件地址的类型 console.log(文档,filetype) uni.downloadFile({url: e,//e是图片地址success(res) {console.log(res)if (res.statusCode 200) {console.log(下载成功,);var filePath encodeURI(res.tempFilePath);…

python开发之远程开发工具对比

前言 除了本地开发外&#xff0c;还有一种常见的开发方式就是远程开发&#xff0c;一般情况是一台Windows或mac笔记本作为日常使用的电脑&#xff0c;另有一台linux服务器作为开发服务器。开发服务器的性能往往较强&#xff0c;这样远程开发的方式一方面可以让我们在习惯的系统…