当前位置: 首页 > news >正文

深入浅出 Python Logging:从基础到进阶日志管理

在这里插入图片描述
在 Python 开发过程中,日志(Logging)是不可或缺的调试和监控工具。合理的日志管理不仅能帮助开发者快速定位问题,还能提供丰富的数据支持,让应用更具可观测性。本文将带你全面了解 Python logging 模块,涵盖日志输出到控制台、文件、Elasticsearch(ES),以及日志格式的介绍。

一、日志输出到控制台

最简单的日志管理方式就是将日志信息输出到控制台(标准输出)。这种方式在调试时非常方便,能够实时查看程序运行状态。默认情况下,Python logging 模块会以 WARNING 级别及以上的日志输出到控制台。

  def add_stream_handle(self):if LOG_TO_CONSOLE and LOG_ENABLED:handler = logging.StreamHandler(sys.stdout)handler.setLevel(level=CONSOLE_LEVEL)handler.setFormatter(logging.Formatter(LOG_FORMAT))self.logger.addHandler(handler)

二、日志输出到文件

在实际开发中,日志不仅仅是为了调试,更重要的是长期存储以便后续分析。因此,我们通常需要将日志写入文件,以便在程序运行后仍能追踪问题。通过 FileHandler,我们可以轻松地将日志写入指定的文件,并支持日志轮转(如按日期或文件大小分割)。

    def add_file_handle(self):if LOG_ENABLED and LOG_TO_FILE:logs_dir = os.path.join(LOG_DIR, "logs")os.makedirs(logs_dir, exist_ok=True)file = os.path.join(logs_dir, f'{datetime.now().strftime("%Y%m%d_%H%M%S")}.log')handler = logging.FileHandler(file, encoding="utf-8")handler.setLevel(level=FILE_LEVEL)handler.setFormatter(logging.Formatter(LOG_FORMAT))self.logger.addHandler(handler)

三、日志输出到 Elasticsearch(ES)

对于需要集中式日志管理的场景,可以将日志直接存储到 Elasticsearch 中,配合 Kibana 进行可视化分析。通过 logging 模块的自定义 Handler 或者 elastic-apm 等第三方库,我们可以将 Python 产生的日志数据直接推送到 ES,并结合全文检索和仪表盘进行日志分析。

class JsonSerializer:"""JSON serializer relying on the standard library json module."""mimetype: ClassVar[str] = "application/json"def default(self, data: Any) -> Any:if isinstance(data, date):return data.isoformat()elif isinstance(data, uuid.UUID):return str(data)elif isinstance(data, Decimal):return float(data)raise Exception(f"Unable to serialize to JSON: {data!r} (type: {type(data).__name__})", )def json_dumps(self, data: dict) -> str:return json.dumps(data, default=self.default, ensure_ascii=False, separators=(",", ":"))def json_loads(self, data: str) -> dict:return json.loads(data)def loads(self, data: str) -> dict:return self.json_loads(data)def dumps(self, data: dict) -> str:# The body is already encoded to bytes# so we forward the request body along.if isinstance(data, str):return datareturn self.json_dumps(data)def _attempt_serialize_numpy(data: Any) -> Tuple[bool, Any]:try:import numpy as npif isinstance(data,(np.int_,np.intc,np.int8,np.int16,np.int32,np.int64,np.uint8,np.uint16,np.uint32,np.uint64,),):return True, int(data)elif isinstance(data,(np.float16,np.float32,np.float64,),):return True, float(data)elif isinstance(data, np.bool_):return True, bool(data)elif isinstance(data, np.datetime64):return True, data.item().isoformat()elif isinstance(data, np.ndarray):return True, data.tolist()except ImportError:# Since we failed to import 'numpy' we don't want to try again.return False, Nonereturn False, Nonedef _attempt_serialize_pandas(data: Any) -> Tuple[bool, Any]:try:import pandas as pdif isinstance(data, (pd.Series, pd.Categorical)):return True, data.tolist()elif isinstance(data, pd.Timestamp) and data is not getattr(pd, "NaT", None):return True, data.isoformat()elif data is getattr(pd, "NA", None):return True, Noneexcept ImportError:# Since we failed to import 'pandas' we don't want to try again.return False, Nonereturn False, Nonedef _attempt_serialize_numpy_or_pandas(data: Any) -> Tuple[bool, Any]:serialized, value = _attempt_serialize_numpy(data)if serialized:return serialized, valueserialized, value = _attempt_serialize_pandas(data)if serialized:return serialized, valuereturn False, NoneTIME_TYPES = (date, datetime)
FLOAT_TYPES = (Decimal,)
INTEGER_TYPES = ()class EsJsonSerializer(JsonSerializer):mimetype: ClassVar[str] = "application/json"def default(self, data: Any) -> Any:if isinstance(data, TIME_TYPES):# Little hack to avoid importing pandas but to not# return 'NaT' string for pd.NaT as that's not a valid# Elasticsearch date.formatted_data = data.isoformat()if formatted_data != "NaT":return formatted_dataif isinstance(data, uuid.UUID):return str(data)elif isinstance(data, FLOAT_TYPES):return float(data)# This is kept for backwards compatibility even# if 'INTEGER_TYPES' isn't used by default anymore.elif INTEGER_TYPES and isinstance(data, INTEGER_TYPES):return int(data)# Special cases for numpy and pandas types# These are expensive to import so we try them last.serialized, value = _attempt_serialize_numpy_or_pandas(data)if serialized:return valueraise TypeError(f"Unable to serialize {data!r} (type: {type(data)})")class EsHandler(logging.Handler):def __init__(self, url, index, batch_size=100, flush_interval=6, extra_fields=None):super().__init__()self.default_raise = Falseself.index = indexself.batch_size = batch_sizeself.flush_interval = flush_intervalself.extra_fields = extra_fields if isinstance(extra_fields, dict) else {}self._buffer = []self.url = urlself._timer = Noneself.serializer = EsJsonSerializer()@staticmethoddef __get_es_datetime_str(timestamp):current_date = datetime.utcfromtimestamp(timestamp)return "{0!s}.{1:03d}Z".format(current_date.strftime('%Y-%m-%dT%H:%M:%S'), int(current_date.microsecond / 1000))def emit(self, record: logging.LogRecord) -> None:self.format(record)rec = self.extra_fields.copy()for key, value in record.__dict__.items():rec[key] = "" if value is None else valuerec["timestamp"] = self.__get_es_datetime_str(record.created)self._buffer.append(rec)# 如果缓存已满,直接刷新if len(self._buffer) >= self.batch_size:self.flush()else:self.schedule_flush()def schedule_flush(self):if self._timer is None:self._timer = Timer(self.flush_interval, self.flush)self._timer.daemon = Trueself._timer.start()def flush(self):# 如果缓存中有日志,则批量写入if self._timer is not None and self._timer.is_alive():self._timer.cancel()self._timer = Noneif self._buffer:try:logs_buffer = self._bufferself._buffer = []self.bulk_data(logs_buffer)except Exception as exception:if self.default_raise:raise exceptiondef bulk_data(self, logs_buffer):print("批量写入 Elasticsearch")request_body = ""for log_record in logs_buffer:actions = {"index": {'_index': self.index, "_id": str(uuid4())}}data = json.dumps(actions)request_body += datarequest_body += "\n"request_body += EsJsonSerializer().json_dumps(log_record)request_body += "\n"request_body += "\n"headers = {'content-type': 'application/json'}requests.post(self.url, data=request_body, headers=headers)def close(self):if self._timer is not None:self.flush()self._timer = None

四、日志格式介绍

字段作用
%(levelname)s日志级别(如 DEBUG、INFO、WARNING、ERROR、CRITICAL),用于标识日志的严重程度。
%(asctime)s日志的时间戳,默认格式为 YYYY-MM-DD HH:MM:SS,mmm(可自定义 datefmt)。
%(process)d进程 ID,表示当前日志属于哪个进程(适用于多进程应用)。
%(filename)s记录日志的 Python 文件名(不包含路径)。
%(name)s记录日志的 Logger 名称,通常是 logging.getLogger(name) 设定的名称。
%(lineno)d代码中的行号,表示日志记录发生的确切位置。
%(module)s模块名称,即 filename 去掉 .py 的部分。
%(message)s实际的日志信息,即 logger.info(“内容”) 传入的内容。
%(levelno)s日志级别的数值(如 DEBUG=10, INFO=20, WARNING=30, ERROR=40, CRITICAL=50)
%(pathname)s记录日志的 Python 文件完整路径。
%(funcName)s记录日志所在的函数名。
%(thread)d线程 ID(适用于多线程应用)。
%(threadName)s线程名称。
%(processName)s记录日志时距 logging 模块加载后的毫秒数。
%(msecs)d记录日志的时间戳的毫秒部分。
# 示例
LOG_FORMAT = '%(levelname)s - %(asctime)s - [PID: %(process)d] [Thread: %(threadName)s] - %(pathname)s - %(funcName)s - Line: %(lineno)d - %(message)s'

五、完整的代码

import logging
import sys
import os
import json
import socket
import time
import uuid
from datetime import date, datetime
from decimal import Decimal
from typing import Any, ClassVar, Mapping, Optional, Tuplefrom threading import Timer
from multiprocessing import Lock
import requests
from uuid import uuid4LOG_ENABLED = True  # 是否开启日志
LOG_TO_CONSOLE = True  # 是否输出到控制台
CONSOLE_LEVEL = "INFO"  # 控制台的日志等级
LOG_TO_FILE = True  # 是否输出到文件
FILE_LEVEL = "INFO"  # 文件的日志等级
LOG_TO_ES = True  # 是否输出到 Elasticsearch
ES_LEVEL = "INFO"  # 输出到ES的日志等级LOG_LEVEL = 'DEBUG'  # 日志级别LOG_FORMAT = '%(levelname)s - %(asctime)s - process: %(process)d - %(filename)s - %(name)s - %(lineno)d - %(module)s - %(message)s'  # 每条日志输出格式ELASTIC_SEARCH_HOST = 'http://192.168.3.200:9200'  # Elasticsearch Host
ELASTIC_SEARCH_INDEX = 'python'  # Elasticsearch Index Name
APP_NAME = "demo-fastapi"
APP_ENVIRONMENT = 'dev'  # 运行环境,如测试环境还是生产环境
LOG_DIR = os.getcwd()class JsonSerializer:"""JSON serializer relying on the standard library json module."""mimetype: ClassVar[str] = "application/json"def default(self, data: Any) -> Any:if isinstance(data, date):return data.isoformat()elif isinstance(data, uuid.UUID):return str(data)elif isinstance(data, Decimal):return float(data)raise Exception(f"Unable to serialize to JSON: {data!r} (type: {type(data).__name__})", )def json_dumps(self, data: dict) -> str:return json.dumps(data, default=self.default, ensure_ascii=False, separators=(",", ":"))def json_loads(self, data: str) -> dict:return json.loads(data)def loads(self, data: str) -> dict:return self.json_loads(data)def dumps(self, data: dict) -> str:# The body is already encoded to bytes# so we forward the request body along.if isinstance(data, str):return datareturn self.json_dumps(data)def _attempt_serialize_numpy(data: Any) -> Tuple[bool, Any]:try:import numpy as npif isinstance(data,(np.int_,np.intc,np.int8,np.int16,np.int32,np.int64,np.uint8,np.uint16,np.uint32,np.uint64,),):return True, int(data)elif isinstance(data,(np.float16,np.float32,np.float64,),):return True, float(data)elif isinstance(data, np.bool_):return True, bool(data)elif isinstance(data, np.datetime64):return True, data.item().isoformat()elif isinstance(data, np.ndarray):return True, data.tolist()except ImportError:# Since we failed to import 'numpy' we don't want to try again.return False, Nonereturn False, Nonedef _attempt_serialize_pandas(data: Any) -> Tuple[bool, Any]:try:import pandas as pdif isinstance(data, (pd.Series, pd.Categorical)):return True, data.tolist()elif isinstance(data, pd.Timestamp) and data is not getattr(pd, "NaT", None):return True, data.isoformat()elif data is getattr(pd, "NA", None):return True, Noneexcept ImportError:# Since we failed to import 'pandas' we don't want to try again.return False, Nonereturn False, Nonedef _attempt_serialize_numpy_or_pandas(data: Any) -> Tuple[bool, Any]:serialized, value = _attempt_serialize_numpy(data)if serialized:return serialized, valueserialized, value = _attempt_serialize_pandas(data)if serialized:return serialized, valuereturn False, NoneTIME_TYPES = (date, datetime)
FLOAT_TYPES = (Decimal,)
INTEGER_TYPES = ()class EsJsonSerializer(JsonSerializer):mimetype: ClassVar[str] = "application/json"def default(self, data: Any) -> Any:if isinstance(data, TIME_TYPES):# Little hack to avoid importing pandas but to not# return 'NaT' string for pd.NaT as that's not a valid# Elasticsearch date.formatted_data = data.isoformat()if formatted_data != "NaT":return formatted_dataif isinstance(data, uuid.UUID):return str(data)elif isinstance(data, FLOAT_TYPES):return float(data)# This is kept for backwards compatibility even# if 'INTEGER_TYPES' isn't used by default anymore.elif INTEGER_TYPES and isinstance(data, INTEGER_TYPES):return int(data)# Special cases for numpy and pandas types# These are expensive to import so we try them last.serialized, value = _attempt_serialize_numpy_or_pandas(data)if serialized:return valueraise TypeError(f"Unable to serialize {data!r} (type: {type(data)})")class EsHandler(logging.Handler):def __init__(self, url, index, batch_size=100, flush_interval=6, extra_fields=None):super().__init__()self.default_raise = Falseself.index = indexself.batch_size = batch_sizeself.flush_interval = flush_intervalself.extra_fields = extra_fields if isinstance(extra_fields, dict) else {}self._buffer = []self.url = urlself._timer = Noneself.serializer = EsJsonSerializer()@staticmethoddef __get_es_datetime_str(timestamp):current_date = datetime.utcfromtimestamp(timestamp)return "{0!s}.{1:03d}Z".format(current_date.strftime('%Y-%m-%dT%H:%M:%S'), int(current_date.microsecond / 1000))def emit(self, record: logging.LogRecord) -> None:self.format(record)rec = self.extra_fields.copy()for key, value in record.__dict__.items():rec[key] = "" if value is None else valuerec["timestamp"] = self.__get_es_datetime_str(record.created)self._buffer.append(rec)# 如果缓存已满,直接刷新if len(self._buffer) >= self.batch_size:self.flush()else:self.schedule_flush()def schedule_flush(self):if self._timer is None:self._timer = Timer(self.flush_interval, self.flush)self._timer.daemon = Trueself._timer.start()def flush(self):# 如果缓存中有日志,则批量写入if self._timer is not None and self._timer.is_alive():self._timer.cancel()self._timer = Noneif self._buffer:try:logs_buffer = self._bufferself._buffer = []self.bulk_data(logs_buffer)except Exception as exception:if self.default_raise:raise exceptiondef bulk_data(self, logs_buffer):print("批量写入 Elasticsearch")request_body = ""for log_record in logs_buffer:actions = {"index": {'_index': self.index, "_id": str(uuid4())}}data = json.dumps(actions)request_body += datarequest_body += "\n"request_body += EsJsonSerializer().json_dumps(log_record)request_body += "\n"request_body += "\n"headers = {'content-type': 'application/json'}requests.post(self.url, data=request_body, headers=headers)def close(self):if self._timer is not None:self.flush()self._timer = Noneclass Logger:_instance = None_lock = Lock()def __init__(self, ):self.logger = logging.getLogger("__file__")self.logger.setLevel(LOG_LEVEL)self.add_stream_handle()self.add_file_handle()self.add_es_handle()def add_stream_handle(self):if LOG_TO_CONSOLE and LOG_ENABLED:handler = logging.StreamHandler(sys.stdout)handler.setLevel(level=CONSOLE_LEVEL)handler.setFormatter(logging.Formatter(LOG_FORMAT))self.logger.addHandler(handler)def add_file_handle(self):if LOG_ENABLED and LOG_TO_FILE:logs_dir = os.path.join(LOG_DIR, "logs")os.makedirs(logs_dir, exist_ok=True)file = os.path.join(logs_dir, f'{datetime.now().strftime("%Y%m%d_%H%M%S")}.log')handler = logging.FileHandler(file, encoding="utf-8")handler.setLevel(level=FILE_LEVEL)handler.setFormatter(logging.Formatter(LOG_FORMAT))self.logger.addHandler(handler)def add_es_handle(self):if LOG_ENABLED and LOG_TO_ES:# 添加 CMRESHandlerurl = f"{ELASTIC_SEARCH_HOST}/_bulk"extra_fields = {"app_name": APP_NAME, "app_env": APP_ENVIRONMENT, 'host': socket.gethostname(),'host_ip': socket.gethostbyname(socket.gethostname())}es_handler = EsHandler(url, index=ELASTIC_SEARCH_INDEX, extra_fields=extra_fields)es_handler.setLevel(level=LOG_LEVEL)formatter = logging.Formatter(LOG_FORMAT)es_handler.setFormatter(formatter)self.logger.addHandler(es_handler)@classmethoddef get_logger(cls):cls._lock.acquire()if cls._instance is None:cls._instance = Logger().loggercls._lock.release()return cls._instanceif __name__ == '__main__':logger = Logger.get_logger()logger.info("INFO")logger.warning("WARNING")logger.error("ERROR")time.sleep(100)

结语

掌握 Python 的 logging 模块,能让你的日志管理更加高效,无论是简单的控制台调试,还是日志文件持久化存储,甚至是对接 ELK 进行集中管理,都是开发者必备的技能。

相关文章:

深入浅出 Python Logging:从基础到进阶日志管理

在 Python 开发过程中,日志(Logging)是不可或缺的调试和监控工具。合理的日志管理不仅能帮助开发者快速定位问题,还能提供丰富的数据支持,让应用更具可观测性。本文将带你全面了解 Python logging 模块,涵盖…...

系统巡检脚本分享:守护服务器的“健康卫士”

在日常的运维工作中,系统巡检是一项至关重要的任务。它可以帮助我们及时发现服务器的潜在问题,确保系统的稳定运行。今天,我想和大家分享一个实用的系统巡检脚本,它能够帮助我们快速、全面地检查服务器的健康状况。 一、为什么需…...

【Elasticsearch】运行时字段(Runtime Fields)索引时定义运行时字段

在 Elasticsearch 中,运行时字段(Runtime Fields)是一种在查询时动态计算的字段,而不是在索引时预先存储的字段。运行时字段为数据处理提供了极大的灵活性,尤其是在处理结构不固定的日志数据或需要动态生成字段值的场景…...

C++从入门到实战(四)C++引用与inline,nullptr

C从入门到实战(四)C引用与inline,nullptr 前言一、C 引用(一)什么是引用(二)引用的特点(三)引用作为函数参数(四)引用作为函数返回值(…...

DeepSeek 助力 Vue 开发:打造丝滑的卡片(Card)

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...

Azure Synapse Dedicated SQL Pool统计指定表中各字段的空值、空字符串或零值比例

-- 创建临时表存储结果 CREATE TABLE #Results (DatabaseName NVARCHAR(128),TableName NVARCHAR(128),ColumnName NVARCHAR(128),DataType NVARCHAR(128),NullOrEmptyCount INT,TotalRows INT,Percentage DECIMAL(10,2) );DECLARE db_name SYSNAME DB_NAME(); -- 获取当前数…...

【深度学习】计算机视觉(CV)-目标检测-SSD(Single Shot MultiBox Detector)—— 单次检测多框检测器

🔹 SSD(Single Shot MultiBox Detector)—— 单次检测多框检测器 1️⃣ 什么是 SSD? SSD (Single Shot MultiBox Detector) 是一种用于 目标检测(Object Detection) 的 深度学习模型,由 Wei L…...

力扣100. 相同的树(利用分解思想解决)

Problem: 100. 相同的树 文章目录 题目描述思路Code 题目描述 思路 题目要求判断两个二叉树是否完全相同,而此要求可以利用问题分解的思想解决,即判断当前节点的左右子树是否完全相同,而在二叉树问题分解的一般题目中均会带有返回值&#xff…...

在SpringBoot服务器端采购上,如何选择操作系统、Cpu、内存和带宽、流量套餐

在Spring Boot服务器端采购时,选择操作系统、CPU、内存、带宽和流量套餐需根据应用需求、预算和性能要求综合考虑。以下是具体建议: 1. 操作系统 Linux发行版(如Ubuntu、CentOS):适合大多数Spring Boot应用&#xff…...

我的新书《青少年Python趣学编程(微课视频版)》出版了!

🎉 激动人心的时刻来临啦! 🎉 小伙伴们久等了,我的第一本新书 《青少年Python趣学编程(微课视频版)》 正式出版啦! 📚✨ 在这个AI时代,市面上的Python书籍常常过于枯燥&…...

elementUI rules 判断 el-cascader控件修改值未生效

今天修改一个前端项目,增加一个多选字段,使用的是el-cascader控件,因页面是通过引用子页面组件形式使用,出现一个点选后再勾选原有值,输入框内不展示或取消后的也未正常隐藏,如果勾选的值是全新的则其他已选…...

深度学习与人工智能:解锁未来的无限可能

在当今这个科技飞速发展的时代,深度学习和人工智能已不再只是科幻小说中的概念,它们正以惊人的速度渗透到我们生活的方方面面,从智能手机上的语音助手到医疗领域的疾病诊断,从自动驾驶汽车到金融市场的风险预测,其影响…...

pwa应用进阶2-动态加载manifest.json文件

接pwa应用进阶-区分AB面-添加安装按钮而且区分不同的系统和浏览器的各种情况继续优化,主要是让manifest.json文件动态加载。 pwa应用进阶2-动态加载manifest.json文件 主要用途如下: 动态切换PWA的清单文件,例如根据不同的语言或者主题加载不…...

UI用例调试_元素能定位到且不在frame内_无法点击/录入文本

关于单据新增,编辑子集信息遇到的2个阻塞点,做记录已供后续参考 1、新增按钮元素能定位,就是无法点击 实现效果: 单据新增时,前面单据数据编辑完之后,开始新增证件信息,需要先点击新增按钮。…...

Python的web框架Flask适合哪些具体的应用开发?

Flask 适用的具体应用及实现案例代码 Flask 是一个轻量级的 Web 应用框架,以其简洁性和灵活性而广受欢迎。以下是 Flask 适合的具体应用场景及相关的实现案例代码: 1. 小型网站或博客 由于 Flask 的简洁性和易于使用的特性,它非常适合用来搭建个人博客或者小型的企业网站…...

oracle使用动态sql将多层级组织展平

ERP或者其他企业管理软件中都会有一张组织机构表,可以写固定sql的方式将其展平获取组织表中的字段信息,如负责人、上级组织负责人、分管领导、成立时间等。但是这种方式有个缺陷,就是如果只写到处理4个层级,那么后期层级增多就无法…...

vue学习笔记10

ChatGPT & Copilot AI 的认知 两个工具 1、ChatGPT 3.5 2、Github Copilot ChatGPT 的基本使用 - Prompt 优化 AI 互动的过程中,容易出现的问题: 1、 AI未能理解问题的核心要点 2、 AI的回答过于宽泛 或 过于具体 3、 AI提供了错误的信息或…...

网络安全常识

随着互联网和移动互联网的持续火热,人们的生活也越来越离不开网络,网络安全,在这个信息化时代显得尤为重要,那么网络攻击和安全,这一攻守之间,主要涵盖哪些要点呢,下面我们就来对此进行抽丝剥茧…...

如何在 Visual Studio Code 中使用 DeepSeek R1 和 Cline?

让我们面对现实吧:像 GitHub Copilot 这样的 AI 编码助手非常棒,但它们的订阅费用可能会在你的钱包里烧一个洞。进入 DeepSeek R1 — 一个免费的开源语言模型,在推理和编码任务方面可与 GPT-4 和 Claude 3.5 相媲美。将它与 Cline 配对&#…...

从Sora到有言:3D视频生成技术的突破与应用

近年来,AIGC领域飞速发展,这个词也越来越高频地出现在了大家的生活中。AIGC 能完成的任务也越来越多,大模型的能力飞速增长 —— 从Deepseek生成文字,到StableDiffusion生成图像,再到Sora可以生成视频。 而现在&#x…...

算法18(力扣136)只出现一次的数字

1、问题 给你一个 非空 整数数组 nums,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。 2、示例 (1&…...

基于HTML5 Canvas 和 JavaScript 实现的烟花动画效果

以下是一个使用 HTML5 Canvas 和 JavaScript 实现的烟花动画效果代码盒子: <!DOCTYPE html> <html> <head><title>烟花效果...

网络变压器的主要电性参数与测试方法(1)

Hqst盈盛&#xff08;华强盛&#xff09;电子导读&#xff1a;网络变压器的主要电性参数与测试方法&#xff08;1&#xff09;.. 今天我们就一起先来看看网络变压器的2个主要电性参数与它的测试方法&#xff1a; 1. 开路电感&#xff08;OCL or Lx----Open Circuit Ind…...

Python + WhisperX:解锁语音识别的高效新姿势

大家好&#xff0c;我是烤鸭&#xff1a; 最近在尝试做视频的质量分析&#xff0c;打算利用asr针对声音判断是否有人声&#xff0c;以及识别出来的文本进行进一步操作。asr看了几个开源的&#xff0c;最终选择了openai的whisper&#xff0c;后来发现性能不行&#xff0c;又换了…...

Qt的isVisible ()函数介绍和判断窗口是否在当前界面显示

1、现象&#xff1a;当Qt的窗口最小化时&#xff0c;isVisible值一定是true&#xff0c;这是正常的。 解释&#xff1a;在Qt中&#xff0c;当你点击窗口的最小化按钮时&#xff0c;Qt内部不会自动调用 hide() 方或 setVisible(false) 来隐藏窗口。相反&#xff0c;它会改变窗口…...

Github 2025-02-12 C开源项目日报 Top7

根据Github Trendings的统计,今日(2025-02-12统计)共有7个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量C项目7Python项目2OpenSSL - 强大的开源加密工具包 创建周期:4012 天开发语言:C协议类型:Apache License 2.0Star数量:23449 个Fork数量:10…...

PostgreSQL 数据类型

PostgreSQL 数据类型 PostgreSQL 是一款功能强大的开源关系型数据库管理系统,它以其出色的性能、灵活的数据类型和强大的扩展性而闻名。在 PostgreSQL 中,数据类型是构建数据库表和执行各种操作的基础。本文将详细介绍 PostgreSQL 中常用的数据类型,并探讨它们的使用场景。…...

synchronized关键字

文章目录 synchronized 关键字介绍synchronized 的内存语义 synchronized 关键字介绍 synchronized 块是 Java 提供的一种原子性 内 置锁&#xff0c; Java 中的每个对象都可以把它当作一个 同步锁来使用 &#xff0c; 这些 Java 内置的使用者看不到的锁被称为内部锁 &#xf…...

MATLAB计算反映热需求和能源消耗的度数日指标(HDD+CDD)(全代码)

目录 度数日(Degree Days, DD)概述计算公式MATLAB计算代码调用函数1:计算单站点的 CDD参考度数日(Degree Days, DD)概述 度数日(Degree Days, DD)是用于衡量建筑、城市和地区的热需求和能源消耗模式的指标。它分为两部分: 加热度日(Heating Degree Days, HDD):当室…...

在Linux中Redis不支持lua脚本的处理方法

redis安装在IP为x.x.x.x的服务器上 redis安装 第一步&#xff0c;安装前&#xff0c;检测系统是否安装了redis。若安装了redis&#xff0c;则需要删除redis&#xff1b;若没有安装redis&#xff0c;则需要安装2.6版本以上的redis。 # 确保Redis版本支持Lua脚本。从Redis 2.6…...

第39周:猫狗识别 2(Tensorflow实战第九周)

目录 前言 一、前期工作 1.1 设置GPU 1.2 导入数据 输出 二、数据预处理 2.1 加载数据 2.2 再次检查数据 2.3 配置数据集 2.4 可视化数据 三、构建VGG-16网络 3.1 VGG-16网络介绍 3.2 搭建VGG-16模型 四、编译 五、训练模型 5.1 上次程序的主要Bug 5.2 修改版…...

SpringBoot自定义starter

首先创建Maven项目 引入依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId><version>3.4.2</version></dependency> </dependencies…...

JVM学习

JVM 1、JVM是一个跨语言的平台&#xff0c;与语言无关 2、java虚拟机规范&#xff1a;一流企业做标准&#xff0c;二流企业做品牌&#xff0c;三流企业做产品 JVM种类 Hotspot&#xff1a;Oracle 公司&#xff0c;有商业版和免费版 open jdk 内部包含免费版本hotspot虚拟机 Jr…...

RAG入门: RetroMAE、BGE、M3、MemoRAG

RAG实际上第一步都是先做Retrieval&#xff0c;关于Retrieval的思路有很多&#xff0c;持续更新&#xff1a; RetroMAE &#xff08;论文RetroMAE: Pre-Training Retrieval-oriented Language Models Via Masked Auto-Encoder&#xff09; RetraoMAE包括两个模块&#xff0c;…...

ruby 的安装

在51cto搜索的资料 ruby on rails的安装 http://developer.51cto.com/art/200906/129669.htm http://developer.51cto.com/art/200912/169391.htm http://developer.51cto.com/art/200908/147276.htm 史上最完整的ruby&#xff0c;rails环境架设配置&#xff08;Apachefast…...

MySQL的备份与还原

备份数据库 使用mysqldump工具是备份MySQL数据库的一种常用方法。mysqldump可以导出数据库的结构和数据到一个SQL文件中&#xff0c;这个文件稍后可以被用来重新创建数据库或恢复数据。以下是mysqldump命令的详细扩写&#xff1a; mysqldump -u <username> -p<passw…...

文心快码|AI重构开发新范式,从工具到人机协同

本系列视频来自百度前端架构师张立理&#xff0c;他在以“应用来了”为主题的2024百度世界大会上&#xff0c;进行了文心快码3.0能力演示&#xff0c;端到端能力展示。 以下视频是关于文心快码全栈编程智能体-AI重构开发新范式 文心快码AI重构开发新范式 百度前端架构师张立理认…...

Windows11+PyCharm利用MMSegmentation训练自己的数据集保姆级教程

系统版本&#xff1a;Windows 11 依赖环境&#xff1a;Anaconda3 运行软件&#xff1a;PyCharm 一.环境配置 通过Anaconda Prompt(anaconda)打开终端创建一个虚拟环境 conda create --name mmseg python3.93.激活虚拟环境 conda activate mmseg 4.安装pytorch和cuda tor…...

方法(构造方法、方法重载、可变参数)

方法&#xff08;Method&#xff09; 方法是组织好的、可以重复使用的代码块&#xff0c;用于实现单一或相关联的功能。方法有助于提高代码的模块化和可读性&#xff0c;并且通过减少代码冗余来促进代码的重用。 一个方法通常包含5中部分组成&#xff1a; 访问修饰符&#xf…...

ES节点配置的最佳实践

一个 Elasticsearch&#xff08;ES&#xff09;节点可以同时包含数据节点和主节点的角色。这种配置在某些场景下是可行的&#xff0c;尤其是在小型集群中。然而&#xff0c;在生产环境中&#xff0c;通常建议将主节点和数据节点的角色分离&#xff0c;以提高集群的稳定性和性能…...

langchain学习笔记之langserve服务部署

langchain学习笔记之langserve服务部署 引言 LangServe \text{LangServe} LangServe简单介绍安装过程示例应用调用模型接口实现交互使用 Requests \text{Requests} Requests方式进行交互 附&#xff1a; server.py \text{server.py} server.py完整代码 引言 本节将介绍 LangSe…...

Docker安装分布式vLLM

Docker安装分布式vLLM 1 介绍 vLLM是一个快速且易于使用的LLM推理和服务库&#xff0c;适合用于生产环境。单主机部署会遇到显存不足的问题&#xff0c;因此需要分布式部署。 分布式安装方法 https://docs.vllm.ai/en/latest/serving/distributed_serving.html2 安装方法 …...

Java SpringBoot的ProblemDetail实现全局异常统一处理让接口不在需要catch/ProblemDetail实现错误处理的标准化

在开发 Web 应用时&#xff0c;有效的错误处理和响应是提升用户体验和系统健壮性的关键。Spring Boot 3.2 引入了对 ProblemDetail 的更好支持&#xff0c;使得错误处理更加标准化和便捷。本文将通过实战演示&#xff0c;带你深入了解如何在 Spring Boot 3.2 中使用 ProblemDet…...

PHP 基础介绍

PHP 学习资料 PHP 学习资料 PHP 学习资料 PHP 是一种广泛使用的开源服务器端脚本语言&#xff0c;尤其适合 Web 开发&#xff0c;能轻松嵌入 HTML 中&#xff0c;生成动态网页内容。接下来&#xff0c;让我们一起了解 PHP 的基础内容。 一、PHP 的安装与配置 在开始编写 PH…...

CI/CD部署打包方法

项目目前部署方式&#xff1a; 各地区服务器打包同一个runner&#xff08;需要互相排队&#xff0c;不并发&#xff09;各地区客户端可以并发打包&#xff0c;同个地区客户端打多个包需要排队 部署方法 下载gitlab-runner&#xff1a; https://docs.gitlab.com/runner/insta…...

Unity-Mirror网络框架-从入门到精通之PlayerTest示例

文章目录 前言示例介绍PlayerReliable,PlayerUnreliable,PlayerHybrid区别PlayerControllerRB和PlayerController区别最后前言 在现代游戏开发中,网络功能日益成为提升游戏体验的关键组成部分。本系列文章将为读者提供对Mirror网络框架的深入了解,涵盖从基础到高级的多个主…...

C++ 设计模式-抽象工厂

C中的抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;它提供了一个接口&#xff0c;用来创建一系列相关或相互依赖的对象&#xff0c;而无需指定它们具体的类。通过抽象工厂模式&#xff0c;客户端可以通过工厂接口获取一系列产…...

ONES 功能上新|ONES Copilot、ONES TestCase、ONES Wiki 新功能一览

ONES Copilot 支持基于当前查看的工作项相关信息&#xff0c;利用 AI 模型&#xff0c;在系统中进行相似工作项的查找&#xff0c;包括基于已关联工作项的相似数据查找。 应用场景&#xff1a; 在查看工作项时&#xff0c;可利用 AI 模型&#xff0c;基于语义相似度&#xff0c…...

Jenkins | Jenkins安装

Jenkins安装 一、前置准备二、启动三、登录 一、前置准备 下载安装包 war包 下载地址: https://www.jenkins.io/ 安装jdk 要求jdk11版本以上 集成maven项目的话 需要有maven 与 git 二、启动 启动命令 需要注意使用jdk11以上的版本 /usr/java/jdk17/bin/java -Xms2048m -X…...

JavaScript设计模式 -- 观察者模式

在实际开发中&#xff0c;经常会遇到这样一种需求&#xff1a;当某个对象状态发生改变时&#xff0c;需要自动通知并更新其他相关对象。观察者模式&#xff08;Observer Pattern&#xff09;正是为了解决这一问题而设计的&#xff0c;它定义了一种一对多的依赖关系&#xff0c;…...