ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python桌面应用实战:构建OpenAI API余额监控工具

Python桌面应用实战:构建OpenAI API余额监控工具 最近在折腾各种AI工具时发现一个痛点无论是使用ChatGPT API还是其他基于OpenAI Codex的第三方服务账户余额的查询体验总是不尽如人意。要么需要登录官网步骤繁琐要么命令行工具界面简陋信息不全。对于频繁调用API的开发者来说一个能实时、清晰、美观地展示余额的工具能极大提升效率和工作愉悦感。于是我动手开发了一款专为Windows平台设计的Codex余额显示工具。它不仅解决了查询不便的问题更在视觉体验上下了功夫力求做到“全网最好看”。本文将完整分享这款工具从设计思路、技术选型、代码实现到打包发布的全部过程。无论你是想直接使用这款工具还是学习如何用Python构建一个兼具功能与颜值的桌面应用这篇文章都能为你提供清晰的指引。1. 背景与核心概念为什么需要专门的余额工具在深入代码之前我们有必要厘清几个核心概念并理解这个工具解决的真正问题。1.1 OpenAI Codex 与 API 余额OpenAI Codex 是驱动GitHub Copilot等产品的AI模型。对于开发者而言更常接触的是OpenAI提供的API服务通过向https://api.openai.com/v1发送请求来使用包括GPT系列、Codex系列在内的各种模型。使用这些API会产生费用费用从我们预先充值的账户余额中扣除。关键点我们通常说的“Codex余额”广义上指的是OpenAI账户中可用于调用其所有API的信用额度Credits而非特指Codex模型。查询这个余额本质上是调用OpenAI提供的账户信息查询接口。1.2 现有查询方式的痛点官网查询需要打开浏览器登录OpenAI官网进入账户设置页面查看。步骤多无法快速获取。命令行CURL虽然可以通过API密钥直接查询但命令较长输出是原始的JSON格式不直观且需要手动解析关键信息。curl https://api.openai.com/v1/dashboard/billing/credit_grants -H Authorization: Bearer YOUR_API_KEY现有第三方工具一些开源命令行工具功能单一界面通常是黑白终端字符缺乏数据可视化如余额消耗趋势美观度和信息密度不足。1.3 工具的核心目标因此我们这款工具的目标非常明确平台专注针对最主流的Windows桌面环境进行开发和优化。功能核心安全、快速地获取并显示OpenAI账户的可用余额、总使用量、剩余额度等信息。体验升级美观的GUI界面告别命令行使用图形化界面信息布局清晰合理。数据可视化通过图表直观展示近期余额消耗趋势。便捷操作支持保存API密钥本地加密、一键查询、定时刷新等。轻量且独立最终打包成独立的EXE文件无需安装Python环境即可运行。2. 环境准备与版本说明“工欲善其事必先利其器”。在开始编码前请确保你的开发环境已就绪。2.1 开发环境与工具操作系统Windows 10 或 Windows 11本教程和工具均针对Windows平台。编程语言Python 3.8 推荐3.9或3.10兼容性和库支持较好。集成开发环境IDEVisual Studio Code (VS Code) 或 PyCharm。本文示例将使用VS Code。版本控制Git可选但推荐用于代码管理。2.2 核心Python库我们将使用以下库请通过pip提前安装pip install requests pip install PyQt5 pip install pyqtgraph pip install pyinstaller各库作用说明requests用于向OpenAI API发送HTTP请求获取账户数据。这是与后端服务交互的核心。PyQt5用于构建图形用户界面GUI。它功能强大能创建出非常专业的桌面应用界面。pyqtgraph一个基于PyQt的图形和可视化库特别擅长快速绘制动态、交互式图表。我们将用它来绘制余额变化曲线。pyinstaller项目完成后用于将Python脚本和所有依赖打包成一个独立的.exe可执行文件方便分发。2.3 获取OpenAI API密钥这是工具运行的必要条件。如果你还没有请按以下步骤获取访问 OpenAI官网 并登录。点击右上角个人头像选择 “View API keys”。点击 “Create new secret key” 生成一个新的API密钥。重要立即复制并妥善保存这个密钥页面关闭后将无法再次查看。该密钥具有账户访问权限请勿泄露。3. 核心原理与技术拆解工具虽小但涉及了前后端协作、数据安全、GUI设计等多个知识点。我们来逐一拆解。3.1 余额查询的API接口分析OpenAI提供了一个用于查询账户信用额度的接口。我们使用requests库调用它。接口信息URL:https://api.openai.com/v1/dashboard/billing/credit_grants方法:GET认证: 在HTTP请求头中携带Bearer TokenAuthorization: Bearer sk-your-api-key-here响应成功示例:{ object: credit_grants, total_granted: 20.0, // 总共授予的金额美元 total_used: 5.4, // 已使用的金额美元 total_available: 14.6, // 剩余可用金额美元 grants: { object: list, data: [ { object: credit_grant, id: cg_xxx, grant_amount: 20.0, used_amount: 5.4, effective_at: 1672531200, expires_at: 1704067200 } ] } }我们的工具主要关注total_available可用余额和total_used已用量并计算使用百分比。3.2 GUI框架选择为什么是PyQt5Python的GUI库有很多如Tkinter、Kivy、wxPython等。选择PyQt5的原因如下功能全面提供丰富的控件按钮、标签、输入框、表格、图表容器等。界面美观默认样式就比Tkinter现代且支持QSS类似CSS进行深度美化。文档与社区拥有成熟的文档和庞大的社区遇到问题容易找到解决方案。与pyqtgraph无缝集成pyqtgraph本身就是为PyQt设计的两者结合绘制图表非常方便。3.3 数据安全考虑API密钥是敏感信息。我们的工具设计遵循以下安全原则本地存储密钥仅加密后存储在用户本地电脑不上传任何服务器。加密存储使用简单的对称加密如cryptography库或base64编码对保存的密钥进行混淆处理防止明文泄露。本文为简化将使用base64进行演示生产环境建议使用更安全的加密方式。内存安全在程序中使用密钥后尽量避免在日志、调试信息中打印完整密钥。3.4 图表绘制的选择pyqtgraph vs matplotlibmatplotlib是Python最著名的绘图库但在GUI中嵌入和实时更新时性能可能成为瓶颈。pyqtgraph的优势在于性能极高专门为实时数据可视化设计处理大量数据点或高频更新时流畅度远胜matplotlib。交互性好内置缩放、平移、数据点提示等交互功能。集成简单直接作为PyQt5的一个QWidget嵌入到界面中管理方便。4. 完整实战一步步构建余额显示工具现在让我们从零开始构建这个工具。我们将创建多个文件来组织代码。4.1 项目结构规划首先创建一个项目文件夹例如codex_balance_tool并在其中创建以下文件codex_balance_tool/ ├── main.py # 程序主入口 ├── ui_mainwindow.py # 主窗口UI逻辑由Qt Designer生成的文件转换而来 ├── balance_checker.py # 负责API查询和数据处理的核心类 ├── config_manager.py # 负责配置API密钥的加密保存与读取 ├── styles.qss # (可选) 用于定义界面样式的QSS文件 └── icon.ico # (可选) 应用程序图标4.2 核心模块配置管理器 (config_manager.py)这个模块负责安全地处理API密钥。# config_manager.py import base64 import json import os from pathlib import Path class ConfigManager: 配置管理器负责API密钥的加密存储和读取 def __init__(self, config_fileconfig.json): # 配置文件通常放在用户目录或程序同级目录 self.config_file Path.home() / .codex_balance_tool / config_file self.config_file.parent.mkdir(parentsTrue, exist_okTrue) # 确保目录存在 def _simple_encrypt(self, plain_text): 简单的Base64编码进行混淆非强加密仅作演示 # 注意Base64不是加密只是编码。实际项目应使用 Fernet (cryptography) 等。 bytes_data plain_text.encode(utf-8) encoded base64.b64encode(bytes_data).decode(utf-8) return encoded def _simple_decrypt(self, cipher_text): Base64解码 try: decoded_bytes base64.b64decode(cipher_text.encode(utf-8)) return decoded_bytes.decode(utf-8) except: return def save_api_key(self, api_key): 保存API密钥到配置文件 config_data { api_key_encrypted: self._simple_encrypt(api_key) } try: with open(self.config_file, w, encodingutf-8) as f: json.dump(config_data, f, indent4) return True except Exception as e: print(f保存配置失败: {e}) return False def load_api_key(self): 从配置文件加载API密钥 if not self.config_file.exists(): return try: with open(self.config_file, r, encodingutf-8) as f: config_data json.load(f) encrypted_key config_data.get(api_key_encrypted, ) return self._simple_decrypt(encrypted_key) except Exception as e: print(f加载配置失败: {e}) return def clear_config(self): 清除配置文件用于退出登录等操作 try: if self.config_file.exists(): self.config_file.unlink() return True except: return False4.3 核心模块余额检查器 (balance_checker.py)这个模块负责与OpenAI API通信并解析返回的数据。# balance_checker.py import requests import json from datetime import datetime from typing import Dict, Optional, Tuple class BalanceChecker: 余额检查器负责调用OpenAI API并解析数据 def __init__(self, api_key: str): self.api_key api_key self.api_url https://api.openai.com/v1/dashboard/billing/credit_grants self.headers { Authorization: fBearer {self.api_key}, Content-Type: application/json } # 用于存储历史记录方便绘图 self.balance_history [] def fetch_balance(self) - Tuple[bool, Dict, str]: 获取余额信息 Returns: Tuple[bool, Dict, str]: (是否成功, 数据字典, 错误信息) if not self.api_key or not self.api_key.startswith(sk-): return False, {}, API密钥无效或为空 try: response requests.get(self.api_url, headersself.headers, timeout15) response.raise_for_status() # 如果状态码不是200抛出HTTPError异常 data response.json() # 记录本次查询的历史数据 record { timestamp: datetime.now().strftime(%m-%d %H:%M), total_available: data.get(total_available, 0), total_used: data.get(total_used, 0) } self.balance_history.append(record) # 只保留最近20条记录 if len(self.balance_history) 20: self.balance_history.pop(0) return True, data, except requests.exceptions.ConnectionError: return False, {}, 网络连接失败请检查网络设置。 except requests.exceptions.Timeout: return False, {}, 请求超时请稍后重试。 except requests.exceptions.HTTPError as e: if response.status_code 401: return False, {}, API密钥无效或已过期请检查并重新输入。 elif response.status_code 429: return False, {}, 请求过于频繁请稍后再试。 else: return False, {}, fAPI请求错误: {e} except json.JSONDecodeError: return False, {}, 服务器返回数据格式异常。 except Exception as e: return False, {}, f发生未知错误: {e} def get_formatted_data(self, raw_data: Dict) - Dict: 将原始API数据格式化为更友好的显示格式 if not raw_data: return {} total_granted raw_data.get(total_granted, 0) total_used raw_data.get(total_used, 0) total_available raw_data.get(total_available, 0) # 计算使用百分比 usage_percent (total_used / total_granted * 100) if total_granted 0 else 0 formatted { total_granted: f${total_granted:.2f}, total_used: f${total_used:.2f}, total_available: f${total_available:.2f}, usage_percent: f{usage_percent:.1f}%, raw_available: total_available, # 用于图表绘制 raw_used: total_used } return formatted4.4 设计主窗口界面 (使用Qt Designer)为了获得“最好看”的界面我们使用Qt Designer进行可视化设计然后转换为Python代码。步骤打开Qt Designer安装PyQt5-tools后会有。创建一个MainWindow。拖拽控件构建界面建议包含QLabel用于显示大标题如“Codex余额助手”。QLineEdit用于输入和显示API密钥设置echoMode为Password用于输入。QPushButton如“保存密钥”、“查询余额”、“清除历史”。QGroupBox分组显示“账户概览”内部用QLabel显示总额、已用、可用、百分比。QWidget作为一个容器用于后面嵌入pyqtgraph图表。QStatusBar在底部显示状态信息如“查询成功”、“网络错误”。QProgressBar用于显示余额使用百分比更直观。合理使用布局管理器QVBoxLayout,QHBoxLayout,QGridLayout排列控件确保窗口缩放时界面不会混乱。将设计好的UI保存为mainwindow.ui文件。将.ui文件转换为.py文件 在项目目录下打开终端执行pyuic5 mainwindow.ui -o ui_mainwindow.py这会生成ui_mainwindow.py文件其中包含了UI的代码定义。我们将在主程序中导入并使用它。4.5 主程序逻辑 (main.py)这是整合所有模块、实现业务逻辑和交互的地方。# main.py import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, QInputDialog from PyQt5.QtCore import QTimer, Qt from PyQt5.QtGui import QFont import pyqtgraph as pg from ui_mainwindow import Ui_MainWindow # 从生成的文件导入UI类 from balance_checker import BalanceChecker from config_manager import ConfigManager class BalanceToolWindow(QMainWindow): 主窗口类 def __init__(self): super().__init__() # 初始化UI self.ui Ui_MainWindow() self.ui.setupUi(self) # 设置窗口标题和图标 self.setWindowTitle(Codex余额显示工具 - Windows版) # self.setWindowIcon(QIcon(icon.ico)) # 如果有图标文件 # 初始化管理器 self.config_manager ConfigManager() self.balance_checker None # 初始化图表 self.init_chart() # 加载保存的API密钥 self.load_saved_api_key() # 连接信号与槽事件处理 self.connect_signals() # 设置定时器用于自动刷新例如每5分钟 self.auto_refresh_timer QTimer() self.auto_refresh_timer.timeout.connect(self.on_query_balance) # 默认不开启自动刷新可由用户勾选开启 # self.auto_refresh_timer.start(5 * 60 * 1000) # 5分钟 # 美化界面设置字体和样式 self.setup_styles() def init_chart(self): 初始化余额历史图表 # 设置图表背景和前景色 pg.setConfigOptions(antialiasTrue) # 抗锯齿 self.plot_widget pg.PlotWidget() self.plot_widget.setBackground(w) # 白色背景 self.plot_widget.setLabel(left, 余额 (USD), colorblack, size12pt) self.plot_widget.setLabel(bottom, 时间, colorblack, size10pt) self.plot_widget.showGrid(xTrue, yTrue, alpha0.3) # 创建曲线 self.balance_curve self.plot_widget.plot(penpg.mkPen(colorblue, width2), symbolo, symbolBrushblue) # 将图表添加到UI中预留的容器 chart_container self.ui.chartContainerWidget # 假设你在Qt Designer里放了一个QWidget并命名为chartContainerWidget layout chart_container.layout() or pg.GraphicsLayoutWidget() layout.addWidget(self.plot_widget) chart_container.setLayout(layout) def load_saved_api_key(self): 启动时加载已保存的API密钥 saved_key self.config_manager.load_api_key() if saved_key: self.ui.apiKeyLineEdit.setText(saved_key) # 自动创建BalanceChecker实例 self.balance_checker BalanceChecker(saved_key) self.ui.statusbar.showMessage(已加载本地保存的API密钥, 3000) def connect_signals(self): 连接按钮点击等事件到对应的处理函数 self.ui.saveKeyButton.clicked.connect(self.on_save_api_key) self.ui.queryButton.clicked.connect(self.on_query_balance) self.ui.clearHistoryButton.clicked.connect(self.on_clear_history) self.ui.autoRefreshCheckBox.stateChanged.connect(self.on_auto_refresh_changed) def setup_styles(self): 设置界面样式提升美观度 # 设置标题字体 title_font QFont() title_font.setPointSize(16) title_font.setBold(True) self.ui.titleLabel.setFont(title_font) # 假设标题Label对象名为titleLabel self.ui.titleLabel.setStyleSheet(color: #2c3e50;) # 设置数字显示的大字体 number_font QFont() number_font.setPointSize(20) number_font.setBold(True) self.ui.availableAmountLabel.setFont(number_font) # 显示可用余额的Label self.ui.availableAmountLabel.setStyleSheet(color: #27ae60;) # 绿色 # 设置进度条样式 self.ui.usageProgressBar.setStyleSheet( QProgressBar { border: 2px solid #bdc3c7; border-radius: 5px; text-align: center; height: 20px; } QProgressBar::chunk { background-color: #e74c3c; border-radius: 3px; } ) def on_save_api_key(self): 保存API密钥按钮点击事件 api_key self.ui.apiKeyLineEdit.text().strip() if not api_key: QMessageBox.warning(self, 警告, API密钥不能为空) return if not api_key.startswith(sk-): QMessageBox.warning(self, 警告, API密钥格式似乎不正确应以sk-开头。) # 不直接返回允许用户尝试保存 if self.config_manager.save_api_key(api_key): self.balance_checker BalanceChecker(api_key) QMessageBox.information(self, 成功, API密钥已保存到本地) self.ui.statusbar.showMessage(密钥已保存, 3000) else: QMessageBox.critical(self, 错误, 保存API密钥失败) def on_query_balance(self): 查询余额按钮点击事件 if not self.balance_checker: QMessageBox.warning(self, 警告, 请先输入并保存有效的API密钥。) return # 清空旧数据提示显示“查询中...” self.ui.statusbar.showMessage(正在查询余额...) QApplication.processEvents() # 让UI立即更新 success, raw_data, error_msg self.balance_checker.fetch_balance() if success: formatted_data self.balance_checker.get_formatted_data(raw_data) self.update_ui_with_data(formatted_data) self.update_chart() self.ui.statusbar.showMessage(f查询成功最后更新: {self.balance_checker.balance_history[-1][timestamp]}, 5000) else: self.ui.statusbar.showMessage(f查询失败: {error_msg}, 5000) QMessageBox.warning(self, 查询失败, error_msg) def update_ui_with_data(self, data: dict): 用查询到的数据更新UI控件 if not data: return self.ui.totalGrantedLabel.setText(data[total_granted]) self.ui.totalUsedLabel.setText(data[total_used]) self.ui.availableAmountLabel.setText(data[total_available]) self.ui.usagePercentLabel.setText(data[usage_percent]) # 更新进度条 (0-100) try: percent float(data[usage_percent].rstrip(%)) self.ui.usageProgressBar.setValue(int(percent)) except: self.ui.usageProgressBar.setValue(0) def update_chart(self): 更新历史余额曲线图 if not self.balance_checker or not self.balance_checker.balance_history: return history self.balance_checker.balance_history timestamps [item[timestamp] for item in history] balances [item[total_available] for item in history] # 设置X轴为索引并显示时间标签 x list(range(len(timestamps))) self.balance_curve.setData(x, balances) # 设置X轴刻度为时间 axis self.plot_widget.getAxis(bottom) axis.setTicks([list(zip(x, timestamps))]) # 将索引映射为时间字符串 def on_clear_history(self): 清除历史记录按钮点击事件 if self.balance_checker: self.balance_checker.balance_history.clear() self.update_chart() self.ui.statusbar.showMessage(历史图表已清除, 3000) def on_auto_refresh_changed(self, state): 自动刷新复选框状态改变事件 if state Qt.Checked: # 获取用户设定的刷新间隔秒这里简化处理默认5分钟 interval_ms 5 * 60 * 1000 self.auto_refresh_timer.start(interval_ms) self.ui.statusbar.showMessage(f已开启自动刷新间隔{interval_ms//60000}分钟, 3000) else: self.auto_refresh_timer.stop() self.ui.statusbar.showMessage(已关闭自动刷新, 3000) def main(): 应用程序入口 app QApplication(sys.argv) app.setStyle(Fusion) # 使用Fusion风格使界面在不同系统上看起来一致 window BalanceToolWindow() window.show() sys.exit(app.exec_()) if __name__ __main__: main()4.6 运行与验证确保所有Python文件main.py,balance_checker.py,config_manager.py,ui_mainwindow.py在同一目录下。在终端中进入该目录运行python main.py程序启动后在API密钥输入框中填入你的OpenAI API密钥点击“保存密钥”。点击“查询余额”按钮。如果网络和密钥正确你将看到账户信息更新并且图表区域会显示余额变化曲线首次只有当前一个点。多次查询后图表会形成历史趋势线。5. 打包为独立EXE文件为了让没有Python环境的Windows用户也能使用我们使用PyInstaller进行打包。在项目目录下创建一个打包规范文件balance_tool.spec可选但推荐用于复杂配置。打开终端执行打包命令pyinstaller --onefile --windowed --iconicon.ico --nameCodex余额助手 main.py参数解释--onefile打包成单个EXE文件。--windowed运行时不显示控制台窗口对于GUI程序。--iconicon.ico指定应用程序图标需准备.ico文件。--nameCodex余额助手指定生成的EXE文件名称。打包完成后在项目目录下的dist文件夹中你会找到Codex余额助手.exe。将此文件发送给其他Windows用户他们双击即可运行。注意首次打包可能会比较慢因为PyInstaller需要收集所有依赖。生成的EXE文件体积较大通常几十MB到上百MB这是正常的因为它包含了Python解释器和所有库。6. 常见问题与排查思路在开发和使用过程中你可能会遇到以下问题问题现象可能原因解决思路运行python main.py时报错No module named PyQt5未安装PyQt5库或安装失败。在终端中运行pip install PyQt5或pip install PyQt5 pyqtgraph。确保使用正确的Python环境。点击“查询余额”后长时间无响应最后报超时错误网络连接问题无法访问api.openai.com。1. 检查电脑网络是否通畅。2. 尝试在浏览器中打开https://api.openai.com看是否被阻断。3. 如果是网络环境问题本工具无法解决需检查本地网络设置。查询返回“API密钥无效或已过期”1. 输入的API密钥错误。2. API密钥已被撤销或过期。3. 密钥所属账户被封禁。1. 仔细核对并重新输入API密钥注意不要有多余空格。2. 登录OpenAI平台检查API密钥列表确认密钥有效且未过期。3. 生成一个新的API密钥并替换。程序启动后界面错乱或控件重叠UI布局文件(.ui)转换或加载有问题或者控件命名与代码中不一致。1. 检查ui_mainwindow.py是否由最新的.ui文件生成。2. 检查main.py中通过self.ui.xxx访问的控件名称是否与Qt Designer中设置的objectName完全一致。打包成EXE后运行闪退1. 缺少动态链接库(DLL)。2. 路径问题导致配置文件无法读写。3. 杀毒软件误报拦截。1. 尝试在干净的Windows虚拟机中测试或使用--add-data参数将数据文件打包进去。2. 在代码中打印日志到文件查看错误信息。3. 将EXE文件添加到杀毒软件的白名单。图表不显示或显示异常pyqtgraph依赖的PyQt5模块可能打包不全。1. 尝试使用pyinstaller --hidden-importPyQt5.QtCore --hidden-importPyQt5.QtGui ...显式指定隐藏导入。2. 在代码中捕获pyqtgraph导入异常给出友好提示。保存的密钥下次启动不见了配置文件路径权限问题或ConfigManager中指定的路径不可写。检查代码中self.config_file的路径当前设置为用户家目录下的隐藏文件夹确保该目录有写入权限。7. 最佳实践与工程建议将这个工具从“能用”提升到“好用”和“安全”还需要注意以下几点7.1 安全性增强强化密钥加密示例中使用的Base64编码仅是简单混淆。对于真正敏感的环境应使用强加密算法。可以考虑使用cryptography库的Fernet对称加密。# 改进的加密示例需安装 cryptography from cryptography.fernet import Fernet # 生成一个密钥并安全保存首次运行时生成 # cipher_suite Fernet.generate_key() # 然后使用 cipher_suite 进行加密解密避免内存驻留在不再需要API密钥字符串时可以尝试用空字符串覆盖变量但Python的垃圾回收机制使得完全从内存中清除敏感数据比较困难。对于极高安全要求可考虑使用操作系统提供的安全内存区域。代码混淆与保护打包成EXE有一定保护作用但并非绝对安全。核心API密钥处理逻辑可以考虑用Cython编译或使用其他原生语言编写。7.2 功能扩展方向多账户支持允许用户添加和管理多个OpenAI API密钥并快速切换查看不同账户的余额。使用量统计除了总余额还可以调用OpenAI的用量接口(/v1/dashboard/billing/usage)查看每日、每月的详细使用情况和费用明细。余额预警设置一个余额阈值如低于5美元当余额低于该值时通过系统通知、邮件或微信机器人发送预警。多平台支持使用如Kivy或Tauri等框架将应用扩展到macOS和Linux平台。主题切换实现深色/浅色主题切换满足不同用户的审美偏好。7.3 代码质量与维护异常处理示例中已包含基本的异常处理在实际项目中应更细致对文件IO、网络请求、数据解析等每一个可能失败的环节进行捕获和友好提示。日志记录添加日志功能使用logging模块将程序运行状态、错误信息记录到文件方便后期排查问题。配置文件将更多设置如自动刷新间隔、图表颜色、请求超时时间抽象到配置文件中提升灵活性。单元测试为BalanceChecker和ConfigManager等核心模块编写单元测试确保逻辑正确。7.4 用户体验优化输入验证在用户输入API密钥时进行实时格式验证如是否以sk-开头长度是否大致合理。加载状态在查询网络数据时将按钮置灰或显示加载动画防止用户重复点击。数据持久化将查询到的历史余额数据也加密保存到本地即使重启程序图表历史也不会丢失。一键复制为余额数字添加“点击复制”功能方便用户使用。通过以上步骤我们不仅完成了一个功能完善、界面美观的Windows桌面工具更实践了从需求分析、技术选型、模块设计、代码实现、调试打包到安全优化的完整软件开发流程。这个工具本身是实用的而开发过程中学到的GUI编程、API调用、数据可视化和打包部署经验更能广泛应用于其他Python桌面项目开发中。
返回列表