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.pswp.cn/pingmian/77368.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/77368.shtml
英文地址,請注明出處:http://en.pswp.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…