好久没有更新过PyQt5相关的专题了,今天正好有空就做一个文件、文件内容检索的小工具。
目的是为了能够很快的完成的在任意磁盘路径下找到我们需要的文件、或是包含某关键词内容的文件。
实现过程依旧是采用我们比较熟悉的PyQt5来完成应用程序的制作,接下来直接进入正题。
有新来的小伙伴没有安装PyQt5的小伙伴可以选择pip或其他的方式安装该模块。
pip install PyQt5 -i https://mirrors.tuna./help/pypi/
下面我们先可以制作一个PyQt5的UI界面,创建一个FileSearchUI类,将UI界面布局、组件及相关的槽函数都放到这个类中来开发。
# 导入PyQt5.QtGui模块
from PyQt5.QtGui import *
# 导入PyQt5.QtCore模块
from PyQt5.QtCore import *
# 导入PyQt5.QtWidgets模块
from PyQt5.QtWidgets import *
# 系统处理模块
import sys
# 文件处理操作模块
import os
# 导入异常处理模块
import traceback
# 正则表达式匹配模块
import re
import images
class FileSearchUI(QWidget):
def __init__(self):
super(FileSearchUI, self).__init__()
self.resize(600, 400)
self.setWindowTitle('文件内容检索器 公众号:Python 集中营')
self.setWindowIcon(QIcon(':/analysis.ico'))
self.target_search_dir = QLineEdit()
self.target_search_dir.setPlaceholderText('目标搜索目录')
self.target_search_dir.setReadOnly(True)
self.target_search_btn = QPushButton()
self.target_search_btn.setText('浏览')
self.target_search_btn.clicked.connect(self.target_search_btn_clk)
self.search_text = QLineEdit()
self.search_text.setPlaceholderText('请输入搜索内容...')
self.search_btn = QPushButton()
self.search_btn.setText('开始搜索')
self.search_btn.clicked.connect(self.search_btn_clk)
self.brower = QTextBrowser()
self.brower.setReadOnly(True)
self.brower.setFont(QFont('宋体', 8))
self.brower.setPlaceholderText('日志处理过程区域...')
self.brower.ensureCursorVisible()
grid = QGridLayout()
grid.addWidget(self.target_search_dir, 0, 0, 1, 2)
grid.addWidget(self.target_search_btn, 0, 2, 1, 1)
grid.addWidget(self.search_text, 1, 0, 1, 3)
grid.addWidget(self.search_btn, 2, 0, 1, 3)
grid.addWidget(self.brower, 3, 0, 1, 3)
self.thread_ = WorkThread(self)
self.thread_.message.connect(self.show_message)
self.thread_.finished.connect(self.finished)
self.setLayout(grid)
def show_message(self, text):
cursor = self.brower.textCursor()
cursor.movePosition(QTextCursor.End)
self.brower.append(text)
self.brower.setTextCursor(cursor)
self.brower.ensureCursorVisible()
def target_search_btn_clk(self):
target_path = QFileDialog.getExistingDirectory(self, '选择文件夹', os.getcwd())
self.target_search_dir.setText(target_path)
def search_btn_clk(self):
self.thread_.start()
self.search_btn.setEnabled(False)
def finished(self, text):
if text is True:
self.search_btn.setEnabled(True)
至此,我们已经完成了检索小工具应用的UI界面的布局、组件以及相关的槽函数的事件点击操作。
该应用的UI界面展示效果如下:
上述代码块已经实现了应用的界面功能,下面就是业务逻辑的实现了,通常为了不影响主线程的运行都会使用专门的子线程来执行业务逻辑。
这里我们创建一个继承自QThread的WorkThread类用于实现文件内容检索的真正功能。
import chardet
from chardet.universaldetector import UniversalDetector
class WorkThread(QThread):
finished = pyqtSignal(bool)
message = pyqtSignal(str)
def __init__(self, parent=None):
super(WorkThread, self).__init__(parent)
self.parent = parent
self.working = True
def __del__(self):
self.working = True
def run(self):
try:
target_search_dir = self.parent.target_search_dir.text().strip()
search_text = self.parent.search_text.text().strip()
if target_search_dir == '':
self.message.emit('目标检索路径不能为空!')
elif search_text == '':
self.message.emit('检索内容不能为空!')
self.message.emit('已设置目标检索路径:')
self.message.emit(target_search_dir)
self.message.emit('已设置检索内容:')
self.message.emit(search_text)
file_name_con_list = []
file_current_list = []
for dirpath, dirnames, filenames in os.walk(target_search_dir):
for filename in filenames:
if search_text in filename:
if os.path.join(dirpath, filename) not in file_name_con_list:
file_name_con_list.append(os.path.join(dirpath, filename))
detector = UniversalDetector()
with open(os.path.join(dirpath, filename), 'rb') as f:
for line in f:
detector.feed(line)
if detector.done:
break
detector.close()
if detector.result['encoding'] is not None and detector.result['encoding'] == 'utf-8':
current_ = f.read().decode('utf-8')
if search_text in current_:
file_current_list.append(os.path.join(dirpath, filename))
self.message.emit('文件名称包含关键字的文件路径:')
self.message.emit('\n'.join(file_name_con_list))
self.message.emit('文件内容包含关键字的文件路径:')
self.message.emit('\n'.join(file_current_list))
self.message.emit('文件内容检索全部完成!')
self.finished.emit(True)
except:
traceback.print_exc()
self.message.emit('程序运行错误,请检查参数设置是否正常!')
self.finished.emit(True)
如上述WorkThread类的代码块就是全部的业务实现逻辑,我们在读取文件判断时使用的二进制的文件读取方式。
之后,将二进制的字符串解码成utf-8的文本字符串再进行搜索匹配并将文件路径发送到主线程的UI界面日志中。
最后则使用python模块的main函数将整个应用完成启动即可。
if __name__ == '__main__':
app = QApplication(sys.argv)
main = FileSearchUI()
main.show()
sys.exit(app.exec_())
下面检索小工具在搜索过程的运行效果展示:
小伙伴们可以将上述所有源代码复制到自己的开发工具中或打包成exe应用程序即可成功启动应用。