python 库 下载 ,整合在一个小程序 UIUIUI


上图
 

import os
import time
import threading
import requests
import subprocess
import importlib
import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
from concurrent.futures import ThreadPoolExecutor, as_completed
from urllib.parse import urljoinclass PackageInstallerApp:def __init__(self, root):self.root = rootself.root.title("Design By Tim")self.root.geometry("800x600")# 默认设置self.install_dir = r"C:\Users\AAA\Python_Package"self.default_packages = ["numpy", "opencv-python", "pyttsx3"]self.mirrors = ["https://pypi.tuna.tsinghua.edu.cn/simple/","https://mirrors.aliyun.com/pypi/simple/","https://pypi.mirrors.ustc.edu.cn/simple/","https://mirrors.bfsu.edu.cn/pypi/web/simple/","https://mirrors.cloud.tencent.com/pypi/simple/","https://mirrors.nju.edu.cn/pypi/web/simple/","https://mirrors.hit.edu.cn/pypi/web/simple/","https://mirror.sjtu.edu.cn/pypi/web/simple/","https://pypi.doubanio.com/simple/","https://mirrors.zju.edu.cn/pypi/web/simple/","https://mirrors.pku.edu.cn/pypi/simple/","https://mirrors.yun-idc.com/pypi/simple/","https://mirrors.neusoft.edu.cn/pypi/web/simple/","https://mirrors.xjtu.edu.cn/pypi/web/simple/","https://mirrors.huaweicloud.com/repository/pypi/simple/"]# UI控件引用self.start_button = Noneself.cancel_button = None# 创建UIself.create_widgets()def create_widgets(self):# 主框架main_frame = ttk.Frame(self.root, padding="10")main_frame.pack(fill=tk.BOTH, expand=True)# 包列表输入ttk.Label(main_frame, text="要下载的包(逗号分隔):").grid(row=0, column=0, sticky=tk.W)self.pkg_entry = ttk.Entry(main_frame, width=50)self.pkg_entry.grid(row=0, column=1, sticky=tk.EW)self.pkg_entry.insert(0, ",".join(self.default_packages))# 安装目录ttk.Label(main_frame, text="安装目录:").grid(row=1, column=0, sticky=tk.W)self.dir_entry = ttk.Entry(main_frame, width=50)self.dir_entry.grid(row=1, column=1, sticky=tk.EW)self.dir_entry.insert(0, self.install_dir)# 按钮框架btn_frame = ttk.Frame(main_frame)btn_frame.grid(row=2, column=0, columnspan=2, pady=10)# 开始按钮self.start_button = ttk.Button(btn_frame, text="开始下载安装", command=self.start_process)self.start_button.pack(side=tk.LEFT, padx=5)# 取消按钮self.cancel_button = ttk.Button(btn_frame, text="取消", command=self.root.quit)self.cancel_button.pack(side=tk.LEFT, padx=5)# 进度条self.progress = ttk.Progressbar(main_frame, orient=tk.HORIZONTAL, length=500, mode='determinate')self.progress.grid(row=3, column=0, columnspan=2, pady=10)# 状态标签self.status_label = ttk.Label(main_frame, text="准备就绪")self.status_label.grid(row=4, column=0, columnspan=2)# 日志输出ttk.Label(main_frame, text="进度日志:").grid(row=5, column=0, sticky=tk.W)self.log_text = scrolledtext.ScrolledText(main_frame, width=80, height=20, state='normal')self.log_text.grid(row=6, column=0, columnspan=2, sticky=tk.NSEW)# 配置网格权重main_frame.columnconfigure(1, weight=1)main_frame.rowconfigure(6, weight=1)def log_message(self, message):self.log_text.config(state='normal')self.log_text.insert(tk.END, message + "\n")self.log_text.config(state='disabled')self.log_text.see(tk.END)self.root.update()def update_progress(self, value):self.progress['value'] = valueself.root.update()def update_status(self, message):self.status_label.config(text=message)self.root.update()def set_ui_state(self, enabled):state = tk.NORMAL if enabled else tk.DISABLEDself.start_button.config(state=state)self.cancel_button.config(state=state)self.root.update()def start_process(self):# 获取用户输入packages = [pkg.strip() for pkg in self.pkg_entry.get().split(",") if pkg.strip()]self.install_dir = self.dir_entry.get().strip()if not packages:messagebox.showerror("错误", "请输入至少一个包名")returnos.makedirs(self.install_dir, exist_ok=True)# 禁用UIself.set_ui_state(False)self.log_text.config(state='normal')self.log_text.delete(1.0, tk.END)self.log_text.config(state='disabled')self.update_progress(0)# 开始下载安装流程threading.Thread(target=self.download_and_install, args=(packages,), daemon=True).start()def download_and_install(self, packages):overall_success = True  # 跟踪整体成功状态try:# 1. 测试镜像源速度self.update_status("正在测试镜像源速度...")self.log_message("="*50)self.log_message("开始测试镜像源速度")fastest_mirrors = self.find_fastest_mirrors()# 2. 下载包self.update_status("开始下载包...")self.log_message("="*50)self.log_message("开始下载包")downloaded_files = []total_packages = len(packages)download_success = Truefor i, package in enumerate(packages):self.update_progress((i/total_packages)*50)mirror = fastest_mirrors[i % len(fastest_mirrors)]success, files = self.download_package(mirror, package)if not success:download_success = Falseoverall_success = Falseself.log_message(f"⚠️ 包 {package} 下载失败,将继续尝试其他包")else:downloaded_files.extend(files)if not download_success:self.log_message("警告: 部分包下载失败")# 3. 安装包self.update_status("开始安装包...")self.log_message("="*50)self.log_message("开始安装包")install_success = Truefor i, file in enumerate(downloaded_files):self.update_progress(50 + (i/len(downloaded_files))*40)if not self.install_package(file):install_success = Falseoverall_success = Falseself.log_message(f"⚠️ 文件 {file} 安装失败")if not install_success:self.log_message("警告: 部分包安装失败")# 4. 验证安装self.update_status("验证安装...")self.log_message("="*50)self.log_message("开始验证安装")verify_success = Truefor i, package in enumerate(packages):self.update_progress(90 + (i/len(packages))*10)if not self.test_installation(package):verify_success = Falseoverall_success = Falseself.log_message(f"⚠️ 包 {package} 验证失败")if not verify_success:self.log_message("警告: 部分包验证失败")self.update_progress(100)# 显示最终结果if overall_success:self.update_status("所有操作成功完成!")self.log_message("="*50)self.log_message("✅ 所有包下载安装完成并验证成功!")messagebox.showinfo("完成", "所有包下载安装完成并验证成功!")else:self.update_status("操作完成,但有错误发生")self.log_message("="*50)self.log_message("⚠️ 操作完成,但部分步骤失败,请检查日志")messagebox.showwarning("完成但有错误", "操作完成,但部分步骤失败,请检查日志了解详情")except Exception as e:self.log_message(f"❌ 发生严重错误: {str(e)}")self.update_status("操作因错误中止")messagebox.showerror("错误", f"处理过程中发生严重错误: {str(e)}")overall_success = Falsefinally:# 重新启用UIself.set_ui_state(True)def find_fastest_mirrors(self):"""找出最快的3个镜像源"""with ThreadPoolExecutor(max_workers=15) as executor:futures = [executor.submit(self.test_mirror_speed, mirror) for mirror in self.mirrors]results = []for future in as_completed(futures):speed, mirror = future.result()if speed != float('inf'):results.append((speed, mirror))self.log_message(f"测试镜像源 {mirror} 速度: {speed:.2f}秒")results.sort()fastest_mirrors = [mirror for speed, mirror in results[:3]]self.log_message(f"最快的3个镜像源: {', '.join(fastest_mirrors)}")return fastest_mirrorsdef test_mirror_speed(self, mirror):"""测试镜像源速度"""try:start = time.time()response = requests.get(urljoin(mirror, "simple/"), timeout=5)if response.status_code == 200:return time.time() - start, mirrorexcept:passreturn float('inf'), mirrordef download_package(self, mirror, package):"""下载单个包"""try:self.log_message(f"正在从 {mirror} 下载 {package}...")cmd = ["python", "-m", "pip", "download", package, "-d", self.install_dir, "-i", mirror, "--trusted-host", mirror.split('//')[1].split('/')[0]]process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)stdout, stderr = process.communicate()if process.returncode == 0:# 获取下载的文件列表files = [f for f in os.listdir(self.install_dir) if f.startswith(package.replace("-", "_"))]self.log_message(f"✅ 成功下载 {package}: {', '.join(files)}")return True, fileselse:self.log_message(f"❌ 下载 {package} 失败: {stderr.strip()}")return False, []except Exception as e:self.log_message(f"❌ 下载 {package} 时发生错误: {str(e)}")return False, []def install_package(self, filename):"""安装单个包"""try:filepath = os.path.join(self.install_dir, filename)self.log_message(f"正在安装 {filename}...")cmd = ["python", "-m", "pip", "install", filepath]process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)stdout, stderr = process.communicate()if process.returncode == 0:self.log_message(f"✅ 成功安装 {filename}")return Trueelse:self.log_message(f"❌ 安装 {filename} 失败: {stderr.strip()}")return Falseexcept Exception as e:self.log_message(f"❌ 安装 {filename} 时发生错误: {str(e)}")return Falsedef test_installation(self, package):"""测试包是否安装成功"""try:# 转换包名(如opencv-python -> opencv_python)import_name = package.replace("-", "_")self.log_message(f"正在验证 {package} 是否可以导入...")module = importlib.import_module(import_name)version = getattr(module, "__version__", "未知版本")self.log_message(f"✅ 验证成功: {package} (版本: {version})")return Trueexcept Exception as e:self.log_message(f"❌ 验证失败: 无法导入 {package} - {str(e)}")return Falseif __name__ == "__main__":root = tk.Tk()app = PackageInstallerApp(root)root.mainloop()



 

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

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

相关文章

Flutter与FastAPI的OSS系统实现

作者:孙嘉成 目录 一、对象存储 二、FastAPI与对象存储 2.1 缤纷云S4服务API对接与鉴权实现 2.2 RESTful接口设计与异步路由优化 三、Flutter界面与数据交互开发 3.1 应用的创建 3.2页面的搭建 3.3 文件的上传 关键词:对象存储、FastAPI、Flutte…

洛谷P3373线段树详解【模板】

洛谷P3373题目概述 洛谷P3373是一道关于线段树的模板题,题目名称为“【模板】线段树 2”。题目的主要要求是对一个长度为 n 的数列进行如下操作: 将某区间每个数乘上一个数。将某区间每个数加上一个数。求出某区间所有数的和。 线段树简介 线段树是一…

【计算机视觉】CV实战项目- COVID 社交距离检测(covid-social-distancing-detection)

COVID 社交距离检测(covid-social-distancing-detection) 一、项目概述二、项目架构三、环境搭建四、运行项目五、输出结果六、常见问题及解决方法报错1. cv2.error: OpenCV(4.11.0) :-1: error: (-5:Bad argument) in function circle报错2 cv2.circle(…

CMake使用教程

一、CMake 简介 CMake 是一个跨平台的构建工具,用于自动化生成不同平台(如 Makefile、Visual Studio、Xcode 等)的构建文件。它的核心是编写 CMakeLists.txt 文件,定义项目的构建规则。 二、安装 CMake Linux: sudo apt-get ins…

大模型Rag - 两大检索技术

一、稀疏检索:关键词匹配的经典代表 稀疏检索是一种基于关键词统计的传统检索方法。其基本思想是:通过词频和文档频率来衡量一个文档与查询的相关性。 核心原理 文档和查询都被表示为稀疏向量(如词袋模型),只有在词…

LNA设计

设计目的 为后级提供足够的增益以克服后级电路噪声 尽可能小的噪声和信号失真 确保输入和输出端的阻抗匹配 确保信号线性度 评价标准 噪声系数 功率增益 工作频率和带宽 输入信号功率动态范围 端口电压驻波比 稳定性 基于SP模型的LNA设计 直流分析 S参数分析 设计指标 &#xf…

Vue 常见组件及使用方式全解析

一、引言 在 Vue 开发中,组件是构建复杂用户界面的基石。通过使用各种常见组件,我们可以快速搭建出功能丰富、交互性强的应用程序。本文将详细介绍 Vue 开发中一些常见组件及其使用方式。 二、基础 UI 组件 (一)按钮组件&#…

设计测试用例模板

面试时问你一个场景,要你设计测试用例,你会怎么回答? 面试官让你设计一个功能的测试用例,比如“上传文件功能”,其实就是想考你: 思维是否全面能不能抓住重点会不会分类和使用测试方法有没有考虑异常情况…

Git 解决“Filename too long”问题

在 Windows 系统中使用 Git 时,遇到 Filename too long 错误通常是由于系统默认的路径长度限制(260 字符)导致的。以下是综合多种场景的解决方案: 一、快速解决方法 启用 Git 长路径支持 通过 Git 配置命令允许处理超长文件名&am…

Spring Boot 3 + SpringDoc:打造接口文档

1、背景公司 新项目使用SpringBoot3.0以上构建,其中需要对外输出接口文档。接口文档一方面给到前端调试,另一方面给到测试使用。 2、SpringDoc 是什么? SpringDoc 是一个基于 Spring Boot 项目的库,能够自动根据项目中的配置、…

Swagger2Refit

把swagger相关接口转成refit格式,以便其他服务调用 使用工具Refitter. Refitter 项目使用教程 Refit Client API Generator for OpenAPI 项目地址: github.com GitCode - 全球开发者的开源社区,开源代码托管平台 安装 Refitter CLI 工具 首先,通过…

【java 13天进阶Day05】数据结构,List,Set ,TreeSet集合,Collections工具类

常见的数据结构种类 集合是基于数据结构做出来的,不同的集合底层会采用不同的数据结构。不同的数据结构,功能和作用是不一样的。数据结构: 数据结构指的是数据以什么方式组织在一起。不同的数据结构,增删查的性能是不一样的。不同…

systemctl管理指令

今天我们来继续学习服务管理指令,接下来才是重头戏-systemctl,那么话不多说,直接开始吧. systemctl管理指令 1.基本语法: systemctl [start | stop | restart | status]服务 注:systemctl指令管理的服务在/usr/lib/ systemd/system查看 2.systemctl设置服务的自…

STM32单片机教程:从零开始打造智能天气时钟

STM32单片机教程:从零开始打造智能天气时钟 大家好!今天我想为大家详细介绍一下我们的STM32课程,以及如何从零基础逐步掌握单片机开发技能,最终实现一个完整的智能天气时钟项目。 课程面向人群 本课程主要面向那些已经通过野火…

Neovim插件深度解析:mcphub.nvim如何用MCP协议重构开发体验

在AI与工具链深度融合的今天,Neovim 作为现代开发者的生产力工具,正通过插件生态不断突破边界。mcphub.nvim 作为一款基于 MCP(Model Context Protocol) 协议的插件,重新定义了Neovim与智能工具的交互方式。它不仅简化了MCP服务器的集成与管理,更通过直观的UI和生态整合,…

第33讲|遥感大模型在地学分类中的初探与实战

目录 🧠 一、什么是“遥感大模型”? 📚 二、遥感大模型在地学分类中的优势 📍三、案例:使用 Segment Anything Model (SAM) 进行遥感地物分割 📦 1. 安装与依赖配置(PyTorch) 🖼 2. 读取遥感图像(可用 Sentinel-2 伪彩色图) 🔧 3. SAM 模型载入 💡 …

MATLAB - 小车倒立摆的非线性模型预测控制(NMPC)

系列文章目录 目录 系列文章目录 前言 一、摆锤/小车组件 二、系统方程 三、控制目标 四、控制结构 五、创建非线性 MPC 控制器 六、指定非线性设备模型 七、定义成本和约束 八、验证非线性 MPC 控制器 九、状态估计 十、MATLAB 中的闭环仿真 十一、使用 MATLAB 中…

JAVA文件I/O

目录 一、三种路径的分类: 1、绝对路径: 2、相对路径: 3、基准目录: 二、文件的种类: 三、利用JAVA操作文件: 1、File类的构造方法: 2、File 类方法的使用: 使用例子&#…

焊接机器人的设计

一、引言 随着制造业的发展,焊接工艺在各个领域得到广泛应用。焊接机器人具有焊接质量高、效率高、劳动强度低等优点,能够满足现代制造业对焊接生产的要求。设计一款性能优良的焊接机器人,对于提高焊接生产的自动化水平和产品质量具有重要意…

Thymeleaf简介

在Java中,模板引擎可以帮助生成文本输出。常见的模板引擎包括FreeMarker、Velocity和Thymeleaf等 Thymeleaf是一个适用于Web和独立环境的现代服务器端Java模板引擎。 Thymeleaf 和 JSP比较: Thymeleaf目前所作的工作和JSP有相似之处,Thyme…