Python使用everything库构建文件搜索和管理工具
作者:winfredzhang
在这篇博客中,我将分享如何使用 Python 的 everytools库构建一个简单的文件搜索和管理工具,这个工具允许用户搜索文件、查看文件路径、导出文件信息到 Excel,以及生成配置文件,文中有相关的代码示例供大家参考,需要的朋友可以参考下
项目概述
这个工具的主要功能包括:
- 文件搜索:用户可以输入关键字来搜索文件。
- 文件管理:用户可以查看搜索结果,选择文件并将其添加到管理列表。
- 数据导出:用户可以将管理列表中的文件信息导出为 Excel 文件。
- 配置文件生成:用户可以生成配置文件,方便后续使用。
环境准备
确保安装了以下库:
pip install wxPython pandas pywin32,everytools
代码实现
以下是完整的代码实现:
import wx from everytools import EveryTools import pandas as pd import os import pythoncom import win32com.client class MyFrame(wx.Frame): def __init__(self, *args, **kw): super(MyFrame, self).__init__(*args, **kw) self.InitUI() self.all_items = [] # 用于存储ListView1的所有项目 def InitUI(self): panel = wx.Panel(self) vbox = wx.BoxSizer(wx.VERTICAL) # 搜索框 self.search_ctrl = wx.TextCtrl(panel, style=wx.TE_PROCESS_ENTER) self.search_ctrl.Bind(wx.EVT_TEXT_ENTER, self.OnSearch) # ListView1 self.list_ctrl1 = wx.ListCtrl(panel, style=wx.LC_REPORT) self.list_ctrl1.InsertColumn(0, 'File Name', width=200) self.list_ctrl1.InsertColumn(1, 'File Path', width=300) self.list_ctrl1.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated) # ListView2 self.list_ctrl2 = wx.ListCtrl(panel, style=wx.LC_REPORT) self.list_ctrl2.InsertColumn(0, 'File Name', width=200) self.list_ctrl2.InsertColumn(1, 'File Path', width=300) # 导出Excel按钮 self.export_button = wx.Button(panel, label='Export to Excel') self.export_button.Bind(wx.EVT_BUTTON, self.OnExport) # 生成配置文件按钮 self.config_button = wx.Button(panel, label='Generate Config File') self.config_button.Bind(wx.EVT_BUTTON, self.OnGenerateConfig) # 删除选中项按钮 self.delete_button = wx.Button(panel, label='Delete Selected') self.delete_button.Bind(wx.EVT_BUTTON, self.OnDelete) # 过滤框 self.filter_ctrl = wx.TextCtrl(panel, style=wx.TE_PROCESS_ENTER) self.filter_ctrl.SetHint("Search ListView1...") self.filter_ctrl.Bind(wx.EVT_TEXT_ENTER, self.OnFilterListView) # 布局 vbox.Add(self.search_ctrl, 0, wx.EXPAND | wx.ALL, 5) vbox.Add(self.filter_ctrl, 0, wx.EXPAND | wx.ALL, 5) vbox.Add(self.list_ctrl1, 1, wx.EXPAND | wx.ALL, 5) vbox.Add(self.list_ctrl2, 1, wx.EXPAND | wx.ALL, 5) vbox.Add(self.export_button, 0, wx.EXPAND | wx.ALL, 5) vbox.Add(self.config_button, 0, wx.EXPAND | wx.ALL, 5) vbox.Add(self.delete_button, 0, wx.EXPAND | wx.ALL, 5) panel.SetSizer(vbox) self.SetTitle('File Search and Management') self.Centre() def OnSearch(self, event): keyword = self.search_ctrl.GetValue() es = EveryTools() es.search(keyword) try: results = es.results() if results.empty: wx.MessageBox("No results found.", "Info", wx.OK | wx.ICON_INFORMATION) return except OSError as e: wx.MessageBox(f"Error retrieving results: {e}", "Error", wx.OK | wx.ICON_ERROR) return except Exception as e: wx.MessageBox(f"An unexpected error occurred: {e}", "Error", wx.OK | wx.ICON_ERROR) return if 'name' not in results.columns or 'path' not in results.columns: wx.MessageBox("Expected columns 'name' or 'path' not found in results.", "Error", wx.OK | wx.ICON_ERROR) return self.list_ctrl1.DeleteAllItems() self.all_items = [] # 重置存储所有项目的列表 for index, row in results.iterrows(): self.list_ctrl1.InsertItem(index, row['name']) self.list_ctrl1.SetItem(index, 1, row['path']) self.all_items.append((row['name'], row['path'])) # 存储所有项目 def OnItemActivated(self, event): index = event.GetIndex() file_name = self.list_ctrl1.GetItemText(index, 0) file_path = self.list_ctrl1.GetItemText(index, 1) self.list_ctrl2.InsertItem(self.list_ctrl2.GetItemCount(), file_name) self.list_ctrl2.SetItem(self.list_ctrl2.GetItemCount() - 1, 1, file_path) def OnExport(self, event): dialog = wx.DirDialog(None, "Choose a directory to save the Excel file:", style=wx.DD_DEFAULT_STYLE) if dialog.ShowModal() == wx.ID_OK: directory = dialog.GetPath() file_path = f"{directory}/exported_files.xlsx" data = [] for i in range(self.list_ctrl2.GetItemCount()): data.append({ 'File Name': self.list_ctrl2.GetItemText(i, 0), 'File Path': self.list_ctrl2.GetItemText(i, 1) }) df = pd.DataFrame(data) df.to_excel(file_path, index=False) wx.MessageBox(f"Data exported successfully to {file_path}", "Info", wx.OK | wx.ICON_INFORMATION) dialog.Destroy() def OnGenerateConfig(self, event): dialog = wx.DirDialog(None, "Choose a directory to save the config file:", style=wx.DD_DEFAULT_STYLE) if dialog.ShowModal() == wx.ID_OK: directory = dialog.GetPath() file_path = os.path.join(directory, "buttons.ini") self.ExportToIni(file_path) wx.MessageBox(f"Config file generated successfully at {file_path}", "Info", wx.OK | wx.ICON_INFORMATION) dialog.Destroy() def ExportToIni(self, path): shell = win32com.client.Dispatch("WScript.Shell") # with open(path, 'w') as file: # for idx, lnk_path in enumerate(self.get_selected_file_paths(), start=1): # try: # if lnk_path.endswith('.lnk'): # shortcut = shell.CreateShortCut(lnk_path) # target_path = shortcut.Targetpath # caption = os.path.splitext(os.path.basename(lnk_path))[0] # else: # # 处理非 .lnk 文件,直接使用文件路径 # target_path = lnk_path # caption = os.path.splitext(os.path.basename(lnk_path))[0] # file.write(f"[Button{idx}]\n") # file.write(f"caption = {caption}\n") # file.write(f"link = {target_path}\n") # file.write("color = clGreen\n") # file.write("width = 150\n") # file.write("height = 70\n\n") # except Exception as e: # wx.MessageBox(f"Error processing file {lnk_path}: {e}", "Error", wx.OK | wx.ICON_ERROR) with open(path, 'w') as file: for idx, lnk_path in enumerate(self.get_selected_file_paths(), start=1): try: if lnk_path.lower().endswith('.lnk'): # 判断文件名后缀是否为".lnk" shortcut = shell.CreateShortCut(lnk_path) target_path = shortcut.Targetpath else: target_path = lnk_path caption = os.path.splitext(os.path.basename(lnk_path))[0] file.write(f"[Button{idx}]\n") file.write(f"caption = {caption}\n") file.write(f"link = {target_path}\n") file.write("color = clGreen\n") file.write("width = 150\n") file.write("height = 70\n\n") except Exception as e: wx.MessageBox(f"Error processing file {lnk_path}: {e}", "Error", wx.OK | wx.ICON_ERROR) # def get_selected_file_paths(self): # """获取所有选定的文件路径""" # file_paths = [] # for i in range(self.list_ctrl2.GetItemCount()): # file_paths.append(self.list_ctrl2.GetItemText(i, 1)) # return file_paths def get_selected_file_paths(self): """获取所有选定的文件路径,包含文件名""" file_paths = [] for i in range(self.list_ctrl2.GetItemCount()): directory_path = self.list_ctrl2.GetItemText(i, 1) # 假设第0列是目录路径 file_name = self.list_ctrl2.GetItemText(i, 0) # 假设第1列是文件名 full_path = os.path.join(directory_path, file_name) file_paths.append(full_path) return file_paths def OnDelete(self, event): selected = self.list_ctrl2.GetFirstSelected() while selected != -1: self.list_ctrl2.DeleteItem(selected) selected = self.list_ctrl2.GetFirstSelected() def resolve_shortcut(self, path): """解析 .lnk 文件,返回它指向的可执行文件完整路径(包含exe名称)""" shell = win32com.client.Dispatch("WScript.Shell") shortcut = shell.CreateShortCut(path) return shortcut.Targetpath # def OnFilterListView(self, event): # filter_text = self.filter_ctrl.GetValue().lower() # self.list_ctrl1.DeleteAllItems() # for index, (name, path) in enumerate(self.all_items): # if filter_text in name.lower() or filter_text in path.lower(): # self.list_ctrl1.InsertItem(index, name) # self.list_ctrl1.SetItem(index, 1, path) # def OnFilterListView(self): # filtered_items = self.filter_items_based_on_some_criteria() # self.list_ctrl1.DeleteAllItems() # for item in filtered_items: # index = self.list_ctrl1.InsertItem(self.list_ctrl1.GetItemCount(), item[0]) # if index != -1: # 确保索引有效 # self.list_ctrl1.SetItem(index, 1, item[1]) # else: # wx.MessageBox(f"Failed to insert item {item[0]}", "Error", wx.OK | wx.ICON_ERROR) # def OnFilterListView(self, event): # # 从过滤框获取输入的过滤条件 # filter_text = self.filter_ctrl.GetValue().lower() # # 清空list_ctrl1中的所有项目 # self.list_ctrl1.DeleteAllItems() # # 遍历所有项目,找到与过滤条件匹配的项目并重新添加到list_ctrl1中 # for index, (name, path) in enumerate(self.all_items): # if filter_text in name.lower() or filter_text in path.lower(): # self.list_ctrl1.InsertItem(index, name) # self.list_ctrl1.SetItem(index, 1, path) def OnFilterListView(self, event): # 从过滤框获取输入的过滤条件 filter_text = self.filter_ctrl.GetValue().lower() # 清空list_ctrl1中的所有项目 self.list_ctrl1.DeleteAllItems() # 遍历所有项目,找到与过滤条件匹配的项目并重新添加到list_ctrl1中 for name, path in self.all_items: if filter_text in name.lower() or filter_text in path.lower(): # 使用InsertItem返回的index new_index = self.list_ctrl1.InsertItem(self.list_ctrl1.GetItemCount(), name) # 使用返回的index设置第二列 self.list_ctrl1.SetItem(new_index, 1, path) def main(): app = wx.App() frame = MyFrame(None) frame.Show() app.MainLoop() if __name__ == '__main__': main()
代码解析
界面布局
代码使用 wx.BoxSizer
来布局界面组件,包括搜索框、两个列表视图和多个按钮。每个组件都有相应的事件绑定,用于处理用户交互。
文件搜索功能
用户在搜索框中输入关键字,按下回车后,程序会调用 EveryTools
类进行搜索,并将结果显示在第一个列表视图中。如果没有找到结果,程序会弹出提示框。
文件管理功能
用户可以通过双击搜索结果,将文件添加到第二个列表视图中。选中的文件可以被删除。
数据导出与配置文件生成
用户可以将第二个列表视图中的文件信息导出为 Excel 文件,或生成配置文件。
结果如下
总结
这个简单的文件搜索和管理工具展示了 everytools的基本用法,适合初学者学习和实践。通过这个项目,您可以了解如何处理用户输入、管理列表视图和文件操作等。
以上就是Python使用everything库构建文件搜索和管理工具的详细内容,更多关于Python everything文件搜索和管理的资料请关注脚本之家其它相关文章!