【开源解析】基于Python的智能文件备份工具开发实战:从定时备份到托盘监控

📁【开源解析】基于Python的智能文件备份工具开发实战:从定时备份到托盘监控

请添加图片描述

🌈 个人主页:创客白泽 - CSDN博客
🔥 系列专栏:🐍《Python开源项目实战》
💡 热爱不止于代码,热情源自每一个灵感闪现的夜晚。愿以开源之火,点亮前行之路。
👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦

请添加图片描述
在这里插入图片描述

概述

在数字化时代,数据备份已成为个人和企业数据管理的重要环节。本文将详细介绍如何使用Python开发一款功能全面的桌面级文件备份工具,该工具不仅支持即时备份,还能实现定时自动备份增量备份等专业功能,并具备系统托盘驻留能力。通过tkinter+ttkbootstrap构建现代化UI界面,结合pystray实现后台运行,是Python GUI开发的经典案例。


功能亮点

  1. 双目录选择:可视化选择源目录和目标目录
  2. 三种备份模式
    • 立即执行备份
    • 每日/每周定时备份
    • 精确到分钟的自定义时间备份
  3. 增量备份机制:仅复制新增或修改过的文件
  4. 实时日志系统:彩色分级日志输出
  5. 进度可视化:带条纹动画的进度条
  6. 托盘驻留:最小化到系统托盘持续运行
  7. 异常处理:完善的错误捕获和提示机制

在这里插入图片描述


技术架构

主界面
目录选择模块
定时设置模块
日志显示模块
每日定时
每周定时
精确时间
备份引擎
文件遍历
增量判断
文件复制
托盘图标

核心代码解析

1. 增量备份实现

def execute_backup(self):for root, dirs, files in os.walk(self.source_path):rel_path = os.path.relpath(root, self.source_path)dest_path = os.path.join(self.dest_path, rel_path)os.makedirs(dest_path, exist_ok=True)for file in files:src_file = os.path.join(root, file)dest_file = os.path.join(dest_path, file)# 增量判断逻辑if not os.path.exists(dest_file):need_copy = True  # 新文件else:src_mtime = os.path.getmtime(src_file)dest_mtime = os.path.getmtime(dest_file)need_copy = src_mtime > dest_mtime  # 修改时间比对

这段代码实现了备份工具的核心功能——增量备份。通过对比源文件和目标文件的修改时间,仅当源文件较新时才执行复制操作,大幅提升备份效率。

2. 定时任务调度

def calculate_next_run(self, hour, minute, weekday=None):now = datetime.now()if weekday is not None:  # 每周模式days_ahead = (weekday - now.weekday()) % 7next_date = now + timedelta(days=days_ahead)next_run = next_date.replace(hour=hour, minute=minute, second=0)else:  # 每日模式next_run = now.replace(hour=hour, minute=minute, second=0)if next_run < now:next_run += timedelta(days=1)return next_run

该算法实现了智能的下一次运行时间计算,支持按日和按周两种循环模式,确保定时任务准确执行。

3. 托盘图标实现

def create_tray_icon(self):image = Image.new('RGBA', (64, 64), (255, 255, 255, 0))draw = ImageDraw.Draw(image)draw.ellipse((16, 16, 48, 48), fill=(33, 150, 243))menu = (pystray.MenuItem("打开主界面", self.restore_window),pystray.MenuItem("立即备份", self.start_backup_thread),pystray.Menu.SEPARATOR,pystray.MenuItem("退出", self.quit_app))self.tray_icon = pystray.Icon("backup_tool", image, menu=menu)threading.Thread(target=self.tray_icon.run).start()

通过Pillow动态生成托盘图标,结合pystray创建右键菜单,实现程序后台持续运行能力。


使用教程

基础备份操作

  1. 点击"选择源目录"按钮指定需要备份的文件夹
  2. 点击"选择目标目录"按钮设置备份存储位置
  3. 点击"立即备份"按钮开始执行备份

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

定时备份设置

  1. 选择定时类型(每日/每周)
  2. 设置具体执行时间
    • 每日模式:只需设置时分
    • 每周模式:需额外选择星期
  3. 点击"确认定时"按钮保存设置

在这里插入图片描述

定时器逻辑层界面用户定时器逻辑层界面用户选择定时类型更新UI选项设置具体时间点击确认按钮计算下次执行时间显示下次备份时间


进阶功能解析

线程安全设计

def start_backup_thread(self):if self.validate_paths():threading.Thread(target=self.execute_backup, daemon=True).start()

采用多线程技术将耗时的备份操作放在后台执行,避免界面卡顿,同时设置为守护线程确保程序能正常退出。

日志系统实现

def log_message(self, message, level="INFO"):color_map = {"INFO": "#17a2b8", "SUCCESS": "#28a745", "WARNING": "#ffc107", "ERROR": "#dc3545"}self.window.after(0, self._append_log, message, level, color_map.get(level))

通过after方法实现线程安全的日志更新,不同级别日志显示不同颜色,方便问题排查。


完整源码下载

import tkinter as tk
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from tkinter import filedialog, messagebox, scrolledtext
import shutil
import os
import sys
from datetime import datetime, timedelta
import threading
from PIL import Image, ImageDraw
import pystrayclass BackupApp:def __init__(self):self.window = ttk.Window(themename="litera")self.window.title("文件备份工具")self.window.geometry("465x700")self.window.resizable(False, False)self.window.minsize(465, 700)self.window.maxsize(465, 700)self.window.protocol("WM_DELETE_WINDOW", self.on_close)self.font = ("微软雅黑", 10)self.source_path = ""self.dest_path = ""self.schedule_type = tk.StringVar(value='')self.scheduled_job = Noneself.current_schedule = {}main_frame = ttk.Frame(self.window, padding=20)main_frame.pack(fill=tk.BOTH, expand=True)dir_frame = ttk.Labelframe(main_frame, text="目录设置", padding=15)dir_frame.pack(fill=tk.X, pady=10)dir_frame.grid_columnconfigure(0, weight=0)dir_frame.grid_columnconfigure(1, weight=1)dir_frame.grid_columnconfigure(2, weight=0)ttk.Button(dir_frame,text="选择源目录",command=self.select_source,bootstyle="primary-outline",width=15).grid(row=0, column=0, padx=5, pady=5, sticky="w")self.source_label = ttk.Label(dir_frame, text="未选择源目录", bootstyle="info")self.source_label.grid(row=0, column=1, padx=5, sticky="w")ttk.Button(dir_frame,text="选择目标目录",command=self.select_destination,bootstyle="primary-outline",width=15).grid(row=1, column=0, padx=5, pady=5, sticky="w")self.dest_label = ttk.Label(dir_frame, text="未选择目标目录", bootstyle="info")self.dest_label.grid(row=1, column=1, padx=5, sticky="w")ttk.Button(dir_frame,text="立即备份",command=self.start_backup_thread,bootstyle="success",width=15).grid(row=0, column=2, rowspan=2, padx=15, sticky="ns")schedule_frame = ttk.Labelframe(main_frame, text="定时设置", padding=15)schedule_frame.pack(fill=tk.X, pady=10)type_frame = ttk.Frame(schedule_frame)type_frame.pack(fill=tk.X, pady=5)ttk.Radiobutton(type_frame,text="每日备份",variable=self.schedule_type,value='daily',bootstyle="info-toolbutton",command=self.update_schedule_ui).pack(side=tk.LEFT, padx=5)ttk.Radiobutton(type_frame,text="每周备份",variable=self.schedule_type,value='weekly',bootstyle="info-toolbutton",command=self.update_schedule_ui).pack(side=tk.LEFT)self.settings_container = ttk.Frame(schedule_frame)custom_frame = ttk.Labelframe(main_frame, text="自定义备份(精确到分钟)", padding=15)custom_frame.pack(fill=tk.X, pady=10)custom_frame.grid_columnconfigure(0, weight=1)custom_frame.grid_columnconfigure(1, weight=0)custom_frame.grid_columnconfigure(2, weight=0)self.date_entry = ttk.DateEntry(custom_frame,bootstyle="primary",dateformat="%Y-%m-%d",startdate=datetime.now().date(),width=13)self.date_entry.grid(row=0, column=0, padx=5, sticky="w")time_selector = ttk.Frame(custom_frame)time_selector.grid(row=0, column=1, padx=(5,10), sticky="w")self.custom_hour = ttk.Combobox(time_selector,width=3,values=[f"{i:02d}" for i in range(24)],bootstyle="primary",state="readonly")self.custom_hour.set("09")self.custom_hour.pack(side=tk.LEFT)ttk.Label(time_selector, text=":").pack(side=tk.LEFT)self.custom_minute = ttk.Combobox(time_selector,width=3,values=[f"{i:02d}" for i in range(60)],bootstyle="primary",state="readonly")self.custom_minute.set("00")self.custom_minute.pack(side=tk.LEFT)ttk.Button(custom_frame,text="预定备份",command=self.custom_backup,bootstyle="success",width=10).grid(row=0, column=2, padx=5, sticky="e")log_frame = ttk.Labelframe(main_frame, text="操作日志", padding=15)log_frame.pack(fill=tk.BOTH, expand=True, pady=10)self.log_area = scrolledtext.ScrolledText(log_frame,wrap=tk.WORD,font=("Consolas", 9),height=8,bg="#f8f9fa",fg="#495057")self.log_area.pack(fill=tk.BOTH, expand=True)self.log_area.configure(state="disabled")self.status_label = ttk.Label(main_frame,text="就绪",bootstyle="inverse-default",font=("微软雅黑", 9))self.status_label.pack(fill=tk.X, pady=10)self.progress = ttk.Progressbar(main_frame,orient='horizontal',mode='determinate',bootstyle="success-striped",length=500)self.progress.pack(pady=10)self.window.bind("<Unmap>", self.check_minimized)self.create_tray_icon()def update_schedule_ui(self):for widget in self.settings_container.winfo_children():widget.destroy()time_frame = ttk.Frame(self.settings_container)time_frame.pack(side=tk.LEFT, fill=tk.X, expand=True)ttk.Label(time_frame, text="执行时间:").pack(side=tk.LEFT)self.hour_var = ttk.Combobox(time_frame,width=3,values=[f"{i:02d}" for i in range(24)],bootstyle="primary",state="readonly")self.hour_var.set("09")self.hour_var.pack(side=tk.LEFT, padx=5)ttk.Label(time_frame, text=":").pack(side=tk.LEFT)self.minute_var = ttk.Combobox(time_frame,width=3,values=[f"{i:02d}" for i in range(60)],bootstyle="primary",state="readonly")self.minute_var.set("00")self.minute_var.pack(side=tk.LEFT)if self.schedule_type.get() == 'weekly':weekday_frame = ttk.Frame(self.settings_container)weekday_frame.pack(side=tk.LEFT, padx=20)self.weekday_selector = ttk.Combobox(weekday_frame,values=["星期一","星期二","星期三","星期四","星期五","星期六","星期日"],state="readonly",width=8,bootstyle="primary")self.weekday_selector.pack()self.weekday_selector.set("星期一")ttk.Button(self.settings_container,text="确认定时",command=self.set_schedule,bootstyle="success",width=10).pack(side=tk.RIGHT, padx=10)self.settings_container.pack(fill=tk.X, pady=10)def on_close(self):if messagebox.askokcancel("退出", "确定要退出程序吗?"):self.quit_app()else:self.minimize_to_tray()def check_minimized(self, event):if self.window.state() == 'iconic':self.minimize_to_tray()def minimize_to_tray(self):self.window.withdraw()self.log_message("程序已最小化到托盘", "INFO")def restore_window(self, icon=None, item=None):self.window.deiconify()self.window.attributes('-topmost', 1)self.window.after(100, lambda: self.window.attributes('-topmost', 0))self.log_message("已恢复主窗口", "SUCCESS")def quit_app(self, icon=None, item=None):self.tray_icon.stop()self.window.destroy()sys.exit()def log_message(self, message, level="INFO"):color_map = {"INFO": "#17a2b8", "SUCCESS": "#28a745", "WARNING": "#ffc107", "ERROR": "#dc3545"}self.window.after(0, self._append_log, message, level, color_map.get(level, "#000000"))def _append_log(self, message, level, color):timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")formatted_msg = f"[{timestamp}] {level}: {message}\n"self.log_area.configure(state="normal")self.log_area.insert(tk.END, formatted_msg)self.log_area.tag_add(level, "end-2l linestart", "end-2l lineend")self.log_area.tag_config(level, foreground=color)self.log_area.see(tk.END)self.log_area.configure(state="disabled")def validate_paths(self):errors = []if not os.path.isdir(self.source_path):errors.append("源目录无效或不存在")if not os.path.isdir(self.dest_path):errors.append("目标目录无效或不存在")if errors:messagebox.showerror("路径错误", "\n".join(errors))return Falsereturn Truedef start_backup_thread(self):if self.validate_paths():self.progress["value"] = 0threading.Thread(target=self.execute_backup, daemon=True).start()def execute_backup(self):try:self.log_message("开始备份准备...", "INFO")total_files = sum(len(files) for _, _, files in os.walk(self.source_path))self.log_message(f"发现待处理文件总数: {total_files}", "INFO")copied_files = 0processed_files = 0for root, dirs, files in os.walk(self.source_path):rel_path = os.path.relpath(root, self.source_path)self.log_message(f"正在处理目录: {rel_path}", "INFO")dest_path = os.path.join(self.dest_path, rel_path)os.makedirs(dest_path, exist_ok=True)for file in files:src_file = os.path.join(root, file)dest_file = os.path.join(dest_path, file)need_copy = Falseif not os.path.exists(dest_file):need_copy = Trueself.log_message(f"新增文件: {file}", "INFO")else:src_mtime = os.path.getmtime(src_file)dest_mtime = os.path.getmtime(dest_file)if src_mtime > dest_mtime:need_copy = Trueself.log_message(f"检测到更新: {file}", "INFO")if need_copy:try:shutil.copy2(src_file, dest_file)copied_files += 1except Exception as e:self.log_message(f"文件 {file} 备份失败: {str(e)}", "ERROR")processed_files += 1self.progress["value"] = (processed_files / total_files) * 100self.window.update()self.progress["value"] = 100self.window.after(0, self.show_completion_popup, copied_files)self.window.after(0, self.reschedule_backup)except Exception as e:self.log_message(f"备份失败:{str(e)}", "ERROR")messagebox.showerror("备份失败", str(e))self.progress["value"] = 0finally:self.window.update_idletasks()def show_completion_popup(self, copied_files):popup = tk.Toplevel(self.window)popup.title("备份完成")popup.geometry("300x150+%d+%d" % (self.window.winfo_x() + 100,self.window.winfo_y() + 100))ttk.Label(popup, text=f"成功备份 {copied_files} 个文件", font=("微软雅黑", 12)).pack(pady=20)popup.after(5000, popup.destroy)close_btn = ttk.Button(popup, text="立即关闭", command=popup.destroy,bootstyle="success-outline")close_btn.pack(pady=10)def reschedule_backup(self):if self.current_schedule:try:next_run = self.calculate_next_run(self.current_schedule['hour'],self.current_schedule['minute'],self.current_schedule.get('weekday'))delay = (next_run - datetime.now()).total_seconds()if delay > 0:if self.scheduled_job:self.window.after_cancel(self.scheduled_job)self.scheduled_job = self.window.after(int(delay * 1000),self.start_backup_thread)self.status_label.configure(text=f"下次备份时间: {next_run.strftime('%Y-%m-%d %H:%M')}",bootstyle="inverse-info")self.log_message(f"已更新下次备份时间: {next_run.strftime('%Y-%m-%d %H:%M')}", "SUCCESS")else:self.log_message("无效的时间间隔,定时任务未设置", "ERROR")except Exception as e:self.log_message(f"重新安排定时失败: {str(e)}", "ERROR")def set_schedule(self):try:if self.schedule_type.get() == 'weekly' and not hasattr(self, 'weekday_selector'):messagebox.showwarning("提示", "请选择具体星期")returnself.current_schedule = {'hour': int(self.hour_var.get()),'minute': int(self.minute_var.get()),'weekday': ["星期一","星期二","星期三","星期四","星期五","星期六","星期日"].index(self.weekday_selector.get()) if self.schedule_type.get() == 'weekly' else None}self.reschedule_backup()except Exception as e:self.log_message(f"定时设置失败:{str(e)}", "ERROR")messagebox.showerror("设置错误", str(e))def calculate_next_run(self, hour, minute, weekday=None):now = datetime.now()if weekday is not None:days_ahead = (weekday - now.weekday()) % 7next_date = now + timedelta(days=days_ahead)next_run = next_date.replace(hour=hour, minute=minute, second=0, microsecond=0)if next_run < now:next_run += timedelta(weeks=1)else:next_run = now.replace(hour=hour, minute=minute, second=0, microsecond=0)if next_run < now:next_run += timedelta(days=1)return next_rundef custom_backup(self):try:selected_date = self.date_entry.entry.get()hour = int(self.custom_hour.get())minute = int(self.custom_minute.get())target_time = datetime.strptime(selected_date, "%Y-%m-%d").replace(hour=hour, minute=minute, second=0)if target_time < datetime.now():raise ValueError("时间不能早于当前时刻")delay = (target_time - datetime.now()).total_seconds()if delay <= 0:raise ValueError("定时时间必须晚于当前时间")self.window.after(int(delay * 1000), self.start_backup_thread)self.log_message(f"已预定备份时间:{target_time.strftime('%Y-%m-%d %H:%M')}", "SUCCESS")self.status_label.configure(text=f"预定备份时间: {target_time.strftime('%Y-%m-%d %H:%M')}",bootstyle="inverse-warning")except Exception as e:self.log_message(f"预定失败:{str(e)}", "ERROR")messagebox.showerror("设置错误", str(e))def create_tray_icon(self):try:image = Image.new('RGBA', (64, 64), (255, 255, 255, 0))draw = ImageDraw.Draw(image)draw.ellipse((16, 16, 48, 48), fill=(33, 150, 243))menu = (pystray.MenuItem("打开主界面", self.restore_window),pystray.MenuItem("立即备份", self.start_backup_thread),pystray.Menu.SEPARATOR,pystray.MenuItem("退出", self.quit_app))self.tray_icon = pystray.Icon("backup_tool",image,"数据备份工具",menu=menu)threading.Thread(target=self.tray_icon.run, daemon=True).start()except Exception as e:messagebox.showerror("托盘错误", f"初始化失败: {str(e)}")sys.exit(1)def select_source(self):path = filedialog.askdirectory(title="选择备份源文件夹")if path:self.source_path = pathself.source_label.config(text=path)self.status_label.config(text="源目录已更新", bootstyle="inverse-success")self.log_message(f"源目录设置为: {path}", "INFO")def select_destination(self):path = filedialog.askdirectory(title="选择备份存储位置")if path:self.dest_path = pathself.dest_label.config(text=path)self.status_label.config(text="目标目录已更新", bootstyle="inverse-success")self.log_message(f"目标目录设置为: {path}", "INFO")if __name__ == "__main__":app = BackupApp()app.window.mainloop()

文件结构

backup_tool/
├── main.py            # 主程序入口
├── requirements.txt   # 依赖库清单
└── README.md          # 使用说明

安装依赖

pip install -r requirements.txt

总结与扩展

本文开发的备份工具具有以下技术亮点:

  1. 采用现代化GUI框架ttkbootstrap,界面美观
  2. 完善的异常处理机制,健壮性强
  3. 支持后台运行,实用性强
  4. 增量备份算法节省时间和存储空间

扩展建议

  • 增加云存储支持(如阿里云OSS、七牛云等)
  • 添加压缩备份功能
  • 实现多版本备份管理
  • 增加邮件通知功能

通过本项目的学习,读者可以掌握:

  • Python GUI开发进阶技巧
  • 定时任务调度实现
  • 系统托盘程序开发
  • 文件操作最佳实践

“数据备份不是可选项,而是必选项。这个工具用200行代码实现了商业软件的核心功能,值得每个开发者学习。”


相关技术栈

  • Python 3.8+
  • tkinter/ttkbootstrap
  • pystray
  • Pillow
  • shutil/os/sys

适用场景

  • 个人文档备份
  • 开发项目版本存档
  • 服务器重要文件备份
  • 自动化运维任务

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

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

相关文章

Windows 环境变量完全指南:系统变量、用户变量与 PATH 详解

1. 什么是环境变量&#xff1f; 环境变量&#xff08;Environment Variables&#xff09;是 Windows 系统中用于存储配置信息的键值对&#xff0c;它们可以影响系统和应用程序的行为。例如&#xff1a; PATH&#xff1a;告诉系统在哪里查找可执行文件&#xff08;如 python、j…

详解RabbitMQ工作模式之工作队列模式

目录 工作队列模式 概念 特点 应用场景 工作原理 注意事项 代码案例 引入依赖 常量类 编写生产者代码 编写消费者1代码 编写消费者2代码 先运行生产者&#xff0c;后运行消费者 先运行消费者&#xff0c;后运行生产者 工作队列模式 概念 在工作队列模式中&#x…

数据结构-非线性结构-二叉树

概述 /** * 术语 * 根节点&#xff08;root node&#xff09;&#xff1a;位于二叉树顶层的节点&#xff0c;没有父节点。 * 叶节点&#xff08;leaf node&#xff09;&#xff1a;没有子节点的节点&#xff0c;其两个指针均指向 None 。 * 边&#xff08;edge&#xff09;&…

芯片笔记 - 手册参数注释

芯片手册参数注释 基础参数外围设备USB OTG&#xff08;On-The-Go&#xff09;以太网存储卡&#xff08;SD&#xff09;SDIO 3.0(Secure Digital Input/Output)GPIO&#xff08;General Purpose Input/Output 通用输入/输出接口&#xff09;ADC&#xff08;Analog to Digital C…

力扣94. 二叉树的中序遍历

94. 二叉树的中序遍历 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2]示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[]示例 3&#xff1a; 输入&#…

深度学习:AI为老年痴呆患者点亮希望之光

引言 随着全球人口老龄化进程的加速&#xff0c;老年痴呆症已成为严重威胁老年人健康和生活质量的公共卫生问题。据世界卫生组织统计&#xff0c;全球每 3 秒钟就有 1 人被诊断为痴呆&#xff0c;预计到 2050 年&#xff0c;全球痴呆患者人数将从目前的约 5000 万激增至 1.52 亿…

抛物线法(二次插值法)

抛物线法简介 抛物线法&#xff08;Quadratic Interpolation Method&#xff09;是一种用于一维单峰函数极值搜索的经典优化方法。该方法通过在区间内选取三个不同的点&#xff0c;拟合一条二次抛物线&#xff0c;并求取这条抛物线的极值点作为新的迭代点&#xff0c;从而逐步…

FreeRTOS如何检测内存泄漏

在嵌入式系统中&#xff0c;内存资源通常非常有限&#xff0c;内存泄漏可能导致系统性能下降甚至崩溃。内存泄漏是指程序分配的内存未被正确释放&#xff0c;逐渐耗尽可用内存。 FreeRTOS作为一种轻量级实时操作系统&#xff08;RTOS&#xff09;&#xff0c;广泛应用于资源受限…

Mockoon 使用教程

文章目录 一、简介二、模拟接口1、Get2、Post 一、简介 1、Mockoon 可以快速模拟API&#xff0c;无需远程部署&#xff0c;无需帐户&#xff0c;免费&#xff0c;跨平台且开源&#xff0c;适合离线环境。 2、支持get、post、put、delete等所有格式。 二、模拟接口 1、Get 左…

如何进行APP安全加固

进行APP安全加固的关键在于代码混淆、加密敏感数据、权限管理、漏洞扫描与修复。其中&#xff0c;代码混淆能有效阻止逆向工程与篡改攻击&#xff0c;提升应用的安全防护能力。通过混淆代码&#xff0c;攻击者难以轻易理解源代码逻辑&#xff0c;从而降低被破解或攻击的风险。 …

【C++】手搓一个STL风格的string容器

C string类的解析式高效实现 GitHub地址 有梦想的电信狗 1. 引言&#xff1a;字符串处理的复杂性 ​ 在C标准库中&#xff0c;string类作为最常用的容器之一&#xff0c;其内部实现复杂度远超表面认知。本文将通过一个简易仿照STL的string类的完整实现&#xff0c;揭示其设…

辰鳗科技朱越洋:紧扣时代契机,全力投身能源转型战略赛道

国家能源局于4月28日出台的《关于促进能源领域民营经济发展若干举措的通知》&#xff08;以下简称《通知》&#xff09;&#xff0c;是继2月民营企业座谈会后深化能源领域市场化改革的关键政策&#xff0c;标志着民营经济在“双碳”目标引领下正式进入能源转型的核心赛道。 自…

Vue实现不同网站之间的Cookie共享功能

前言 最近有小伙伴在聊天室中提到这么一个需求&#xff0c;就是说希望用户在博客首页中登录了之后&#xff0c;可以跳转到管理系统去发布文章。这个需求的话就涉及到了不同网站之间cookie共享的功能&#xff0c;那么咱们就来试着解决一下这个功能。 实现方式 1. 后端做中转 …

在一台服务器上通过 Nginx 配置实现不同子域名访问静态文件和后端服务

一、域名解析配置 要实现通过不同子域名访问静态文件和后端服务&#xff0c;首先需要进行域名解析。在域名注册商或 DNS 服务商处&#xff0c;为你的两个子域名 blog.xxx.com 和 api.xxx.com 配置 A 记录或 CNAME 记录。将它们的 A 记录都指向你服务器的 IP 地址。例如&#x…

Opencv进阶操作:图像拼接

文章目录 前言一、图像拼接的原理1. 特征提取与匹配2. 图像配准3. 图像变换与投影4. 图像融合5. 优化与后处理 二、图像拼接的简单实现&#xff08;案例实现&#xff09;1.引入库2.定义cv_show()函数3.创建特征检测函数detectAndDescribe()4.读取拼接图片5.计算图片特征点及描述…

LLM 论文精读(三)Demystifying Long Chain-of-Thought Reasoning in LLMs

这是一篇2025年发表在arxiv中的LLM领域论文&#xff0c;主要描述了长思维链 Long Chain-of-Thought 对LLM的影响&#xff0c;以及其可能的生成机制。通过大量的消融实验证明了以下几点&#xff1a; 与shot CoT 相比&#xff0c;long CoT 的 SFT 可以扩展到更高的性能上限&…

计算机网络常识:缓存、长短连接 网络初探、URL、客户端与服务端、域名操作 tcp 三次握手 四次挥手

缓存&#xff1a; 缓存是对cpu&#xff0c;内存的一个节约&#xff1a;节约的是网络带宽资源 节约服务器的性能 资源的每次下载和请求都会造成服务器的一个压力 减少网络对资源拉取的延迟 这个就是浏览器缓存的一个好处 表示这个html页面的返回是不要缓存的 忽略缓存 需要每次…

《构建社交应用用户激励引擎:React Native与Flutter实战解析》

React Native凭借其与JavaScript和React的紧密联系&#xff0c;为开发者提供了一个熟悉且灵活的开发环境。在构建用户等级体系时&#xff0c;它能够充分利用现有的前端开发知识和工具。通过将用户在社交应用中的各种行为进行量化&#xff0c;比如发布动态的数量、点赞评论的次数…

接口自动化测试框架详解(pytest+allure+aiohttp+ 用例自动生成)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 近期准备优先做接口测试的覆盖&#xff0c;为此需要开发一个测试框架&#xff0c;经过思考&#xff0c;这次依然想做点儿不一样的东西。 接口测试是比较讲究效…

Linux-----文件系统

文件大家都知道&#xff0c;前面的我的博客课程也为大家解释了关于文件的打开等&#xff0c;今天我们要谈论的是 文件在没被打开的时候在磁盘中的位置和找到它的方式。 画图为大家展示&#xff1a; 方便理解 我们从下面几个方面入手&#xff1a; 1. 看看物理磁盘 2. 了解一…