日志记录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 sysRANK = 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-8formatter = logging.Formatter("%(message)s")  # Default formatterif 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 iosys.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 StreamHandlerstream_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 = Falsereturn 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 variablen = len(pkgs)  # number of packages updatesLOGGER.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() - tLOGGER.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 Falseelse:return False
  • 案例2
def on_pretrain_routine_end(trainer):global mlflowuri = 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 namesexperiment_name = os.environ.get("MLFLOW_EXPERIMENT_NAME") or trainer.args.project or "/Shared/YOLOv8"run_name = os.environ.get("MLFLOW_RUN") or trainer.args.namemlflow.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 standoffLOGGER.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 heartbeatsLOGGER.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 integrationPatchPyTorchModelIO.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 gigabytesn = min(self.ni, 30)  # extrapolate from 30 random imagesfor _ in range(n):im = cv2.imread(random.choice(self.im_files))  # sample imageratio = self.imgsz / max(im.shape[0], im.shape[1])  # max(h, w)  # ratiob += im.nbytes * ratio**2mem_required = b * self.ni / n * (1 + safety_margin)  # GB required to cache dataset into RAMmem = psutil.virtual_memory()cache = mem_required < mem.available  # to cache or not to cache, that is the questionif 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.rhkb.cn/news/242042.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【RTOS】快速体验FreeRTOS所有常用API(1)工程创建

目录 一、工程创建1.1 新建工程1.2 配置RCC1.3 配置SYS1.4 配置外设1&#xff09;配置 LED PC132&#xff09;配置 串口 UART13&#xff09;配置 OLED I2C1 1.5 配置FreeRTOS1.6 工程设置1.7 生成代码1.8 keil设置下载&复位1.9 添加用户代码 快速体验FreeRTOS所有常用API&a…

k8s的对外服务--ingress

service作用体现在两个方面 1、集群内部 不断跟踪pod的变化&#xff0c;更新endpoint中的pod对象&#xff0c;基于pod的IP地址不断变化的一种服务发现机制 2、集群外部 类似负载均衡器&#xff0c;把流量ip端口&#xff0c;不涉及转发url&#xff08;http&#xff0c;https&a…

list上

文章目录 初步了解list面试题&#xff1a;为什么会有list&#xff1f;vector的缺点&#xff1a;vector、list优点 list结构迭代器的分类list的简单运用insert、erase、迭代器失效&#xff08;和vector的区别&#xff09;erase class和structlist的迭代器为什么这个迭代器的构造…

PGSQL安装PostGIS扩展模块

一、PostGIS简介 1、PostGIS介绍 PostGIS是一个空间数据库&#xff0c;空间数据库像存储和操作数据库中其他任何对象一样去存储和操作空间对象。 空间数据与数据库关联起来的三个要素&#xff1a;数据类型、索引和函数。 空间数据类型&#xff1a;用于指定图形为点&#xff0…

指向未来: 量子纠缠的本质是一个指针

指向未来: 量子纠缠的本质是一个指针 概述基本概念理解量子纠缠PythonJavaC 理解波粒二象性PythonJavaC 理解量子隧穿理解宇宙常量PythonJavaC 概述 量子纠缠 (Quantum Entanglement) 是量子系统重两个或多个粒子间的一种特殊连接, 这种连接使得即使相隔很远, 这些粒子的状态也…

Linux系统CPU持续飙高,如何排查?

一、检查CPU使用率 首先在Linux系统中检查CPU使用率。可以通过在命令行中输入top或htop命令来查看当前系统中各个进程的CPU使用率。如果CPU使用率大于80%&#xff0c;则可以考虑进行排查。 $ top 二、检查系统负载 另外可以使用uptime命令来查看系统的平均负载情况。 $ upti…

第二次作业+第三次作业

第二次作业第三次作业 第二次作业 题目&#xff1a; 网站需求&#xff1a; ​ 1.基于域名[www.openlab.com](http://www.openlab.com)可以访问网站内容为 welcome to openlab!!! 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c;基于[ww…

Python连接数据库的梳理

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

day2:TCP、UDP网络通信模型

思维导图 机械臂实现 #include <head.h> #define SER_POTR 8899 #define SER_IP "192.168.125.223" int main(int argc, const char *argv[]) {//创建套接字int cfdsocket(AF_INET,SOCK_STREAM,0);if(cfd-1){perror("");return -1;}//链接struct so…

Elasticsearch 数据类型相关总结:快速参考指南【记录】

在Elasticsearch中&#xff0c;有多种数据类型可用于定义字段。 在开始了解数据类型之前&#xff0c;首先要知道&#xff0c;在Elasticsearch中&#xff0c;分词处理主要针对文本字段&#xff0c;而对于其他类型字段&#xff08;如数值、日期、布尔等&#xff09;&#xff0c;通…

虚幻UE 材质-进阶边界混合之运行时虚拟纹理

之前在学习空山新雨后时对于边缘虚化过渡处理有很多技术 今天又要介绍一个边缘过渡的方法&#xff1a;运行时虚拟纹理 文章目录 前言一、运行时虚拟纹理二、使用步骤总结 前言 边缘过渡柔和的方式我们之前介绍了很多&#xff0c;但是效果也不是最好的。 像素偏移PDO和我们今天…

解决国内Linux服务器无法使用Github的方法

解决思路&#xff1a;修改Host https://www.ipaddress.com/ 利用上面的网站查询github.com和raw.githubusercontent.com的DNS解析的IP地址 最后&#xff0c;修改服务器的/etc/hosts 添加如下两行&#xff1a; 140.82.112.3 github.com 185.199.108.133 raw.githubuserconte…

IntelliJ IDEA 常用快捷键一览表(通用型,提高编写速度,类结构、查找和查看源码,替换与关闭,调整格式)

文章目录 IntelliJ IDEA 常用快捷键一览表1-IDEA的日常快捷键第1组&#xff1a;通用型第2组&#xff1a;提高编写速度&#xff08;上&#xff09;第3组&#xff1a;提高编写速度&#xff08;下&#xff09;第4组&#xff1a;类结构、查找和查看源码第5组&#xff1a;查找、替换…

bash shell基础命令(一)

文章目录 1.shell启动2. shell提示符3. bash手册3.1 man手册解读 4. 浏览Linux文件系统4.1 遍历目录4.1.1 绝对路径4.1.2 相对路径 4.2 列出目录和文件4.3 处理文件4.3.1创建文件4.3.2 复制文件4.3.3 链接文件4.3.3.1.软链接4.3.3.2 硬链接 4.3.4 文件重命名4.3.5 删除文件4.3.…

获取域控的方法

在域渗透中、作为渗透测试人员&#xff0c;获取域控的权限基本上可以获取整个内网的权限 1.高权限读取本地密码 当域管理员在域成员机器上登录进行工作的时候&#xff0c;会将明文密码保存在本地进行的lsass.exe&#xff0c;可以通过 mimikatz来读取到本地的明文密码。 priv…

HarmonyOS应用开发者高级认证试题库(鸿蒙)

目录 考试链接&#xff1a; 流程&#xff1a; 选择&#xff1a; 判断 单选 多选 考试链接&#xff1a; 华为开发者学堂华为开发者学堂https://developer.huawei.com/consumer/cn/training/dev-certification/a617e0d3bc144624864a04edb951f6c4 流程&#xff1a; 先进行…

01-开始Rust之旅

1. 下载Rust 官方推荐使用 rustup 下载 Rust&#xff0c;这是一个管理 Rust 版本和相关工具的命令行工具。下载时需要连接互联网。 这边提供了离线安装版本。本人学习的机器环境为&#xff1a; ubuntu x86_64&#xff0c;因此选用第②个工具链&#xff1b; 1. rust-1.75.0-x86_…

设计模式的学习笔记

设计模式的学习笔记 一. 设计模式相关内容介绍 1 设计模式概述 1.1 软件设计模式的产生背景 设计模式最初并不是出现在软件设计中&#xff0c;而是被用于建筑领域的设计中。 1977 年美国著名建筑大师、加利福尼亚大学伯克利分校环境结构中心主任 Christopher Alexander 在…

Vue 3 hooks的基本使用及疑问

前言 vue3也用过一段时间了&#xff0c;hooks听说过&#xff0c;但是一直没有用过。公司的前端项目里也没有相应的应用&#xff0c;因此打算系统的学习一下。 hooks与普通函数的区别 以实现一个加法功能为例。 普通函数未抽离 <template><div class"box&quo…

STM32 GD32 瑞萨 psoc 等单片机 无线wifi蓝牙最佳解决方案

新联鑫威一系列低功耗高性价比sdio wifi/蓝牙combo的模块CYWL6208 , CYWL6312, CYW6209等可以搭配stm32 各种型号例如以下,支持sta/ap/apsta&#xff0c;双模蓝牙的应用&#xff0c;支持rt-thread, freertos, Azure RTOS, Linux, Android系统. 稳定强&#xff0c;功耗低&#x…