【Python 打造高效文件分类工具】

【Python】 打造高效文件分类工具

    • 一、代码整体结构
    • 二、关键代码解析
      • (一)初始化部分
      • (二)界面创建部分
      • (三)核心功能部分
      • (四)其他辅助功能部分
    • 三、运行与使用
    • 四、示图
    • 五、作者有话说

该代码基于 Python 的 tkinter 库实现了 “文件分类工具 - 优化版” 图形化桌面应用。用户能通过界面选择文件夹和要分类的文件类型,支持全选或自定义部分文件扩展名进行分类。采用多线程技术执行文件整理任务,避免界面卡顿且可中途停止。利用 os.scandir 高效遍历文件并批量分组处理,对大文件(超 500MB)增加延迟处理并记录日志。通过消息队列记录整理过程,包含跳过文件、移动文件及错误信息等,支持将日志保存为文本文件。整理完成后显示总文件数、成功移动数、失败次数和跳过文件数等统计信息,还可直接打开整理后的文件夹查看结果。

一、代码整体结构

我们的文件分类工具基于 Python 的 Tkinter 库构建,Tkinter 是 Python 的标准 GUI(Graphical User Interface,图形用户界面)库,它提供了丰富的组件来创建交互式应用程序。整个代码围绕一个名为FileOrganizerApp的类展开,这个类负责管理界面元素、用户交互以及文件整理的核心逻辑。

二、关键代码解析

(一)初始化部分

class FileOrganizerApp:def __init__(self, root):self.root = rootself.root.title("文件分类工具-优化版")self.root.geometry("800x600")# 初始化统计变量self.total_files = 0self.moved_count = 0self.error_count = 0self.current_progress = 0# 初始化文件类型选择相关变量self.all_files_var = tk.BooleanVar()self.checkbox_vars = {}self.checkboxes = {}self.preset_extensions = ["txt", "doc", "docx", "pdf", "jpg","png", "gif", "mp3", "mp4", "xls","xlsx", "zip", "rar", "ppt", "pptx"]# 创建消息队列self.log_queue = queue.Queue()self.create_widgets()self.running = Falseself.stop_event = threading.Event()

在__init__ 方法中,我们首先设置了应用程序窗口的标题和初始大小。接着,初始化了一系列统计变量,用于记录整理过程中的文件总数、成功移动的文件数、出错的文件数以及当前的进度。
为了让用户能够选择要分类的文件类型,我们定义了all_files_var布尔变量用于全选功能,checkbox_vars字典来存储每个文件扩展名对应的复选框状态,checkboxes字典用于存储复选框组件,preset_extensions列表则列出了我们预设支持分类的文件扩展名。
消息队列log_queue用于在不同线程间传递日志信息,确保界面的流畅更新。最后,调用create_widgets方法创建界面元素,并初始化一些控制变量。

(二)界面创建部分

def create_widgets(self):# 文件夹选择部分frame_top = ttk.Frame(self.root, padding=10)frame_top.pack(fill=tk.X)self.btn_select = ttk.Button(frame_top, text="选择文件夹", command=self.select_directory)self.btn_select.pack(side=tk.LEFT, padx=5)self.path_var = tk.StringVar()self.entry_path = ttk.Entry(frame_top, textvariable=self.path_var, width=60)self.entry_path.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)# 文件类型选择部分type_frame = ttk.LabelFrame(self.root, text="选择要分类的文件类型", padding=10)type_frame.pack(fill=tk.BOTH, expand=True, pady=5)# 全选复选框ttk.Checkbutton(type_frame,text="全部分类",variable=self.all_files_var,command=self.toggle_checkboxes).grid(row=0, column=0, sticky=tk.W, padx=5)# 创建扩展名复选框for idx, ext in enumerate(self.preset_extensions):self.checkbox_vars[ext] = tk.BooleanVar()cb = ttk.Checkbutton(type_frame,text=ext.upper(),variable=self.checkbox_vars[ext])cb.grid(row=idx // 5 + 1, column=idx % 5, sticky=tk.W, padx=5)self.checkboxes[ext] = cb# 控制按钮部分frame_controls = ttk.Frame(self.root, padding=10)frame_controls.pack(fill=tk.X)self.btn_start = ttk.Button(frame_controls, text="开始整理", command=self.start_organize)self.btn_start.pack(side=tk.LEFT, padx=5)self.btn_stop = ttk.Button(frame_controls, text="停止", command=self.stop_organize, state=tk.DISABLED)self.btn_stop.pack(side=tk.LEFT, padx=5)# 保存日志按钮self.btn_save_log = ttk.Button(frame_controls, text="保存日志", command=self.save_log, state=tk.DISABLED)self.btn_save_log.pack(side=tk.LEFT, padx=5)# 查看文件按钮,初始状态为禁用self.btn_view_files = ttk.Button(frame_controls, text="查看文件", command=self.open_folder, state=tk.DISABLED)self.btn_view_files.pack(side=tk.LEFT, padx=5)# 日志显示部分frame_log = ttk.Frame(self.root, padding=10)frame_log.pack(fill=tk.BOTH, expand=True)self.log_area = scrolledtext.ScrolledText(frame_log, wrap=tk.WORD)self.log_area.pack(fill=tk.BOTH, expand=True)# 进度条self.progress = ttk.Progressbar(self.root, orient=tk.HORIZONTAL, mode='determinate')self.progress.pack(fill=tk.X, padx=10, pady=5)

create_widgets方法负责构建应用程序的整个界面。它分为几个主要部分:

  1. 文件夹选择部分:包含一个按钮btn_select用于打开文件选择对话框,以及一个输入框entry_path用于显示用户选择的文件夹路径。
  2. 文件类型选择部分:通过一个标签框架type_frame包含一个全选复选框和多个文件扩展名复选框。全选复选框的command参数绑定到toggle_checkboxes方法,用于切换所有扩展名复选框的状态。
  3. 控制按钮部分:包括开始整理按钮btn_start、停止按钮btn_stop(初始状态为禁用)、保存日志按钮btn_save_log(初始状态为禁用)和查看文件按钮btn_view_files(初始状态为禁用)。这些按钮分别绑定到对应的功能方法。
  4. 日志显示部分:使用scrolledtext.ScrolledText组件创建一个可滚动的文本区域log_area,用于显示文件整理过程中的日志信息。
  5. 进度条部分:通过ttk.Progressbar创建一个水平进度条progress,用于直观展示文件整理的进度。

(三)核心功能部分

def start_organize(self):if not self.path_var.get():messagebox.showwarning("警告", "请先选择要整理的文件夹")returnif self.running:returnself.running = Trueself.stop_event.clear()self.btn_start['state'] = tk.DISABLEDself.btn_stop['state'] = tk.NORMALself.btn_save_log['state'] = tk.DISABLEDself.btn_view_files['state'] = tk.DISABLEDself.progress['value'] = 0self.log_area.delete(1.0, tk.END)# 启动队列处理self.process_log_queue()self.update_progress()worker = threading.Thread(target=self.organize_files, daemon=True)worker.start()

start_organize方法是启动文件整理流程的入口。首先,它检查用户是否选择了要整理的文件夹路径,如果没有则弹出警告框提示用户。然后,检查当前是否已经在运行整理任务,如果是则直接返回。

接着,设置运行状态变量running为True,清除停止事件stop_event,并根据任务状态更新界面按钮的状态,清空进度条和日志区域。

为了确保日志能够及时更新,调用process_log_queue方法启动日志队列处理,同时调用update_progress方法开始更新进度条。最后,创建一个新的线程来执行核心的文件整理逻辑organize_files,并将线程设置为守护线程,这样当主线程结束时,该线程也会自动结束。

def organize_files(self):target_dir = self.path_var.get()try:# 使用更高效的scandir遍历文件files = []with os.scandir(target_dir) as entries:for entry in entries:if entry.is_file():files.append(entry.name)self.total_files = len(files)processed_files = 0# 批量分组处理文件selected_exts = Noneif not self.all_files_var.get():selected_exts = {ext for ext, var in self.checkbox_vars.items() if var.get()}file_groups = defaultdict(list)skipped_count = 0for filename in files:if self.stop_event.is_set():break_, ext = os.path.splitext(filename)ext = ext.lower().lstrip('.') if ext else 'no_extension'if selected_exts is None or ext in selected_exts:file_groups[ext].append(filename)else:skipped_count += 1# 处理跳过的文件self.log_queue.put(f"已跳过 {skipped_count} 个未选类型的文件")# 批量移动文件total_to_process = sum(len(v) for v in file_groups.values())processed = 0for ext, filenames in file_groups.items():if self.stop_event.is_set():breakdest_dir = os.path.join(target_dir, ext)os.makedirs(dest_dir, exist_ok=True)for filename in filenames:if self.stop_event.is_set():breakfile_path = os.path.join(target_dir, filename)try:# 大文件处理(超过500MB时增加延迟)file_size = os.path.getsize(file_path)if file_size > 500 * 1024 * 1024:self.log_queue.put(f"正在处理大文件: {filename} ({file_size // 1024 // 1024}MB)")time.sleep(0.5)shutil.move(file_path, os.path.join(dest_dir, filename))self.moved_count += 1# 每处理50个文件更新一次日志if self.moved_count % 50 == 0:self.log_queue.put(f"已移动 {self.moved_count} 个文件")except Exception as e:self.error_count += 1self.log_queue.put(f"错误: {filename} ({str(e)})")processed += 1self.current_progress = (processed / total_to_process) * 100self.root.after(10, self.organize_complete)except Exception as e:self.log_queue.put(f"系统错误: {str(e)}")self.root.after(10, self.organize_complete)

organize_files方法是文件分类的核心逻辑所在。它首先获取用户选择的目标文件夹路径target_dir。然后,使用os.scandir函数更高效地遍历目标文件夹中的所有文件,将文件列表存储在files变量中,并记录文件总数total_files。

接下来,根据用户在界面上选择的文件类型进行分组处理。如果用户选择了全部分类(all_files_var为True),则selected_exts为None,表示处理所有文件;否则,通过列表推导式获取用户勾选的文件扩展名集合selected_exts。
使用defaultdict创建file_groups字典,将文件按扩展名分组。在遍历文件过程中,如果文件类型不在用户选择的范围内,则跳过该文件并记录跳过的文件数。

在批量移动文件阶段,首先计算需要处理的文件总数total_to_process。对于每个文件组,创建对应的目标文件夹(如果不存在),然后逐个移动文件。在移动文件时,增加了对大文件(超过 500MB)的处理逻辑,当遇到大文件时,在日志中记录并增加 0.5 秒的延迟,以避免在处理大文件时导致系统卡顿。同时,每成功移动 50 个文件,在日志中记录已移动的文件数。如果移动过程中出现错误,记录错误信息并增加错误计数。

在整个过程中,根据已处理文件数和总文件数实时更新当前进度current_progress。最后,通过root.after方法在 10 毫秒后调用organize_complete方法,用于处理整理完成后的后续操作。

(四)其他辅助功能部分

def stop_organize(self):self.stop_event.set()self.log_queue.put("正在停止整理进程...")

stop_organize方法用于停止文件整理任务。它通过设置stop_event事件,通知正在执行文件整理的线程停止操作,并在日志队列中添加停止进程的提示信息。

def process_log_queue(self):try:while True:msg = self.log_queue.get_nowait()self.log_area.insert(tk.END, msg + "\n")self.log_area.see(tk.END)except queue.Empty:passself.root.after(100, self.process_log_queue)

process_log_queue方法负责从日志队列log_queue中获取日志信息,并将其显示在日志区域log_area中。它通过一个循环不断尝试从队列中获取消息,使用get_nowait方法避免阻塞。如果队列为空,捕获queue.Empty异常并跳过。每次获取并显示消息后,通过root.after方法设置 100 毫秒后再次调用自身,以实现实时更新日志。

def update_progress(self):self.progress['value'] = self.current_progressself.root.after(100, self.update_progress)

update_progress方法用于更新进度条的显示。它将当前进度current_progress的值设置到进度条progress上,并通过root.after方法设置 100 毫秒后再次调用自身,以实现进度条的实时更新。

def organize_complete(self):self.running = Falseself.btn_start['state'] = tk.NORMALself.btn_stop['state'] = tk.DISABLEDself.btn_save_log['state'] = tk.NORMAL# 整理完成后启用查看文件按钮self.btn_view_files['state'] = tk.NORMALself.current_progress = 100stats_message = (f"\n整理完成:\n"f"总文件数: {self.total_files}\n"f"成功移动: {self.moved_count}\n"f"失败次数: {self.error_count}\n"f"跳过文件: {self.total_files - self.moved_count - self.error_count}")self.log_queue.put(stats_message)messagebox.showinfo("整理统计", stats_message)

organize_complete方法在文件整理完成后被调用。它首先将运行状态变量running设置为False,并恢复界面按钮的初始状态,启用开始按钮、禁用停止按钮、启用保存日志按钮和查看文件按钮。同时,将进度条设置为 100%。
然后,生成整理统计信息字符串stats_message,包含总文件数、成功移动的文件数、失败次数和跳过的文件数。将统计信息添加到日志队列中,并通过messagebox.showinfo弹出对话框显示整理统计结果。

def save_log(self):log_text = self.log_area.get(1.0, tk.END)file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files", "*.txt")])if file_path:try:with open(file_path, 'w', encoding='utf-8') as f:f.write(log_text)messagebox.showinfo("保存成功", "日志已成功保存。")except Exception as e:messagebox.showerror("保存失败", f"保存日志时出现错误:{str(e)}")

save_log方法用于将日志区域中的内容保存为文本文件。它首先获取日志区域的所有文本内容log_text,然后通过filedialog.asksaveasfilename打开文件保存对话框,让用户选择保存路径和文件名。如果用户选择了保存路径,尝试将日志内容写入文件。如果保存成功,弹出提示框告知用户;如果保存过程中出现错误,捕获异常并弹出错误提示框。

def open_folder(self):folder = self.path_var.get()if folder:try:if os.name == 'nt':  # Windows 系统os.startfile(folder)elif os.name == 'posix':  # Linux 或 macOS 系统webbrowser.open(folder)except Exception as e:messagebox.showerror("错误", f"打开文件夹时出错: {str(e)}")

open_folder方法用于在文件整理完成后,打开用户选择的目标文件夹。它
首先获取用户在界面上选择的文件夹路径folder。如果路径存在,根据当前操作系统类型进行不同的操作:对于 Windows 系统,使用os.startfile函数打开文件夹;对于 Linux 或 macOS 系统,使用webbrowser.open函数打开文件夹。如果在打开过程中出现异常,捕获异常并通过messagebox.showerror弹出错误提示框,告知用户打开文件夹时出现的错误信息。

三、运行与使用

当你运行这段代码时,会弹出一个图形化界面的文件分类工具窗口。在窗口中,你可以通过点击 “选择文件夹” 按钮选择需要整理文件的文件夹路径,该路径会显示在输入框中。

在 “选择要分类的文件类型” 区域,你可以选择 “全部分类”,也可以单独勾选需要分类的文件扩展名类型,如 “TXT”“JPG”“PDF” 等。完成选择后,点击 “开始整理” 按钮,工具将开始扫描文件夹内的文件,并按照你选择的类型进行分类整理。

在整理过程中,进度条会实时显示整理进度,日志区域会记录整理过程中的详细信息,包括每个文件的处理情况、错误信息等。如果在整理过程中你想停止操作,可以点击 “停止” 按钮。整理完成后,你可以点击 “保存日志” 按钮将整理过程中的日志信息保存为文本文件,也可以点击 “查看文件” 按钮直接打开整理后的文件夹查看分类结果。

四、示图

在这里插入图片描述

五、作者有话说

代码功能已经过严格测试,确认无误。然而,值得注意的是,测试集的大小仅为3个G,相对而言规模较小,因此无法百分之百保证在所有情况下均无任何问题。鉴于此,强烈建议在使用之前做好数据备份,以防万一出现数据丢失的情况。如果您在使用过程中发现任何bug或问题,欢迎随时留言反馈,作者将及时响应并进行相应的修改。

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

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

相关文章

网络工程师 (43)IP数据报

前言 IP数据报是互联网传输控制协议(Internet Protocol,IP)的数据报格式,由首部和数据两部分组成。 一、首部 IP数据报的首部是控制部分,包含了数据报传输和处理所需的各种信息。首部可以分为固定部分和可变部分。 固定…

Leetcode 424-替换后的最长重复字符

给你一个字符串 s 和一个整数 k 。你可以选择字符串中的任一字符,并将其更改为任何其他大写英文字符。该操作最多可执行 k 次。 在执行上述操作后,返回 包含相同字母的最长子字符串的长度。 题解 可以先做LCR 167/Leetcode 03再做本题 滑动窗口&…

28 在可以控制 postgres 服务器, 不知道任何用户名的情况下怎 进入 postgres 服务器

前言 最近有这样的一个需求, 有一个 postgres 服务器 但是 不知道 他的任何的用户名密码, 但是我想要查询这台 postgres 服务器 然后 基于这个需求, 我们看一下 怎么来处理 pg_hba.conf 认证方式修改为 trust 首先将 postgres 服务器的认证方式修改为 trust 这时候 …

LM Studio笔记

一、什么是 LM Studio? LM Studio 是一款功能强大、易于使用的桌面应用程序,用于在本地机器上实验和评估大型语言模型(LLMs)。它允许用户轻松地比较不同的模型,并支持使用 NVIDIA/AMD GPU 加速计算。 功能集&#xff1…

内网下,Ubuntu (24.10) 离线安装docker最新版教程

一般在数据比较敏感的情况下,是无法使用网络的,而对于Ubuntu系统来说,怎么离线安装docker呢? 下面我给大家来讲一下: 采用二进制安装: 1.下载docker离线包 官网下载: Index of linux/static…

框架ThinkPHP(小迪网络安全笔记~

免责声明:本文章仅用于交流学习,因文章内容而产生的任何违法&未授权行为,与文章作者无关!!! 附:完整笔记目录~ ps:本人小白,笔记均在个人理解基础上整理,…

sql数据执行失败,三个命令依次执行

set global innodb_strict_mode off set global.sql_mode ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION; set sql_mode ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION;

【网络安全】零基础入门网络安全劝退指北

作为从16年接触网络安全的小白,谈谈零基础如何入门网络安全,有不对的地方,请多多指教。 这些年最后悔的事情莫过于没有把自己学习的东西积累下来形成一个知识体系。 如何入门 简单了解网络安全 网络安全就是指的确保网络系统中的数据不被别…

【Linux】网络基础

目录 一、协议分层 (一)计算机网络 (二)协议分层 (三)OSI模型 (四)TCP/IP协议 二、网络传输过程 三、IP地址和MAC地址 (一)IP地址 (二&a…

ms-swift3 序列分类训练

目录 引言 一、数据集准备 二、训练/推理代码 2.1 训练 2.2 推理 三、性能验证 引言 swift 3.x支持了序列分类Command Line Parameters — swift 3.2.0.dev0 documentation 想尝试一下用多模态(图像)的序列分类与普通的图像分类任务有啥区别 一、…

STC 51单片机63——关于STC8H的ADC通道切换问题

使用STC8H时,发现在ADC中断中只能使用一个通道,即使切换了通道,那么数据要不为0,要不就是原先通道的电压。查阅手册,内容并不多,没有发现专门提到的问题。只能去试试,最后发现在ADC中断中&#…

大数据处理如何入门

大数据处理的入门可以从以下几个方面入手: 1. 基础知识学习 在深入大数据领域之前,建议先掌握一些基础知识,包括数据类型、存储与处理的基本概念,以及常用的数据处理工具。例如,Python或Java编程语言在大数据领域应用…

Logistic Regression 逻辑回归中的sigmoid函数是什么?

Sigmoid函数是一种在数学、计算机科学,尤其是在机器学习和深度学习领域广泛应用的函数,以下是关于它的详细介绍: 定义与公式 Sigmoid函数的数学表达式为: S ( x ) = 1 1 + e − x S(x)=\frac{1}{1 + e^{-x}} S(x)=1+e−x1​,其中 x x x 可以是一个实数、向量或矩阵。当 …

什么是Spring Boot?

Spring Boot 是基于 Spring 框架的扩展工具,旨在简化 Spring 应用的初始搭建和开发流程。它通过约定优于配置和自动装配机制,减少了传统 Spring 开发中的繁琐配置,使开发者能快速构建独立运行、生产级别的应用。 Spring Boot 的核心特性 自动…

后端生成二维码,前端请求接口生成二维码并展示,且多个参数后边的参数没有正常传输问题处理

一、后端代码 1、controller GetMapping("/generateQRCode/{url}")ApiOperation(value "生成url链接二维码",notes "生成url链接二维码")public JsonResult<NewsQRCodeVo> generateQRCode(PathVariable String url,HttpServletRespons…

计算机网络(3)TCP格式/连接

1、TCP三大特点&#xff1a;面向连接、可靠、基于字节流 2、如何唯一确定一个TCP连接&#xff1f;TCP四元组&#xff1a;源地址、源端口、目的地址、目的端口 源地址和目标地址的字段(32 位)是在 IP 头部中&#xff0c;作用是通过 IP 协议发送报文给对方主机源端口和目标端口…

Visual Studio Code使用ai大模型编成

1、在Visual Studio Code搜索安装roo code 2、去https://openrouter.ai/settings/keys官网申请个免费的配置使用

Flowith.io 初探:DeepSeek-R1免费用,用画布式 AI 提升效率和创意

摘要 介绍了 Flowith.io&#xff0c;一款创新的画布式 AI 平台&#xff0c;旨在提升效率和创意。它通过独特的画布交互、Oracle AI 系统、知识花园和丰富的模型选择&#xff0c;为用户提供全新的 AI 体验。画布交互打破线性思维&#xff0c;Oracle AI 帮助任务拆解与执行&#…

JavaEE-SpringBoot快速入门

文章目录 本节目标Maven什么是Maven创建一个Maven项目maven项目功能maven的依赖管理全球仓库, 私服, 本地服务器, 配置国内镜像 第一个SpringBoot项目创建项目运行SpringBoot程序 SpringBoot原理初步Web服务器 总结 本节目标 了解什么是maven, 配置国内源使用Springboot创建项…

Win11配置wsl、ubuntu、docker

系统要求 安装WSL。 开通虚拟化&#xff1a; 准备工作 dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestartdism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestartwsl --set-default-versi…