【開源解析】基于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.pswp.cn/web/78972.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/78972.shtml
英文地址,請注明出處:http://en.pswp.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. 了解一…