项目环境
编辑日期: 2024-11-28 文章阅读: 次
这是第五个Python小项目,做一个文件定位器。 查找某目录下所有文件,包含指定查找串的文件。注意,这里不仅仅匹配文件名,而是搜索文件的内容。 为了加快搜索速度,本身这又是一个IO任务,所以选用至多同时存活500个线程的技术,加快搜索进度。
项目环境
使用os
、threading
内置模块,用于操作目录和文件,多线程相关。
click
模块之前介绍过,主要用于封装命令行接口,使用方便。
Python版本是3.7.2
import os
import threading
import click
功能演示
文末下载模块代码后,打开命令行窗口,执行下面一行代码,使用-t
指定要查找的关键字线程
,-p
指定查找目录,指在当前目录的父级目录下查找:
python str_finder.py -t 线程 -p ..
打印结果,分割线上是查找的文件,在此没有贴上来。
分割线下面是查找的结果,报告使用多少个线程,同时存活线程数,待查找的关键字线程
位于哪些文件中,如下所示:
-------------------------------------------------------------------------
共使用6个线程
同时存活线程数2
线程 found in ../python-small-examples2/python-small-examples/README.md
线程 found in ../python-small-examples2/python-small-examples/md/120.md
线程 found in ../python-small-examples2/python-small-examples/md/121.md
线程 found in ../python-small-examples2/python-small-examples/md/118.md
线程 found in ../python-small-examples2/python-small-examples/md/119.md
线程 found in ../python-small-examples2/python-small-examples/md/122.md
线程 found in ../python-small-examples2/python-small-examples/md/123.md
线程 found in ../python-small-examples2/python-small-examples/all.md
线程 found in ../python-small-projects/Python200小例子.md
线程 found in ../python-small-projects/str_finder.py
线程 found in ../10个可视化作品-作者zhenguo/作品15-Matplotlib动图/爬虫案例.md
再查找雪花
,使用下行命令:
python str_finder.py -t 雪花 -p ..
----------------------------------------------------------------------------------------------------
共使用6个线程
同时存活线程数2
雪花 found in ../python-small-examples2/python-small-examples/README.md
雪花 found in ../python-small-examples2/python-small-examples/md/141.md
雪花 found in ../python-small-examples2/python-small-examples/all.md
雪花 found in ../publish-book/视频文字稿.md
雪花 found in ../python-small-projects/Python200小例子.md
代码逐行解释
项目只由一个模块str_finder.py
,模块中包括TextFinder
类,下面主要讲解类的组成。
TextFinder类
TextFinder
类包括:
三个类属性
对外公开方法get_files
递归私有方法__get_files
线程方法__task
下面分别介绍这四个构建。
类属性
前两个类属性已注释,第三个属性表示查找支持的文件后缀,目前默认为下面4种:
max_thread_cnt = 500 # 同时存活线程数最大500
big_byte_file = 0.05 # MB
ext_list = ['.csv', '.txt', '.md', '.py', '.java']
```
### 对外公开方法`get_files`
主要包括调用私有方法`__get_files`
同时,通过`join`,等待所有线程执行完成后,主线程才开始执行`print('-' * 100)`及以下代码:
```python
def get_files(self):
self.__get_files(self.path)
for thr in self.threads:
thr.join()
print('-' * 100)
print(f'共使用{len(self.threads)}个线程')
print(f'同时存活线程数{self._live_thread_cnt}')
if len(self.result) == 0:
print(self.text + " not found! ")
else:
for res in self.result:
print(res)
```
### 递归私有方法`__get_files`
递归查找满足后缀的文件
同时存活线程数不能超过默认值,主要考虑内存的负载。
```python
def __get_files(self, path):
files = os.listdir(path)
for name in files:
path_name = os.path.join(path, name)
if os.path.isdir(path_name):
self.__get_files(path_name)
if self.__in_extensions(name):
file_byte = os.stat(path_name).st_size / 1024 / 1024
if file_byte > TextFinder.big_byte_file:
if threading.active_count() < TextFinder.max_thread_cnt:
big_file_proc = threading.Thread(target=self.__task, args=(path_name,))
big_file_proc.start()
self.threads.append(big_file_proc)
self._live_thread_cnt = max(self._live_thread_cnt, threading.active_count())
else:
self.__task(path_name)
else:
self.__task(path_name)
```
线程内的`target`等于`__task`,`open`和`read`的IO操作适合Python的多线程处理,加快查找:
```python
def __task(self, path_name):
print(f'正在查找 {path_name}')
f = open(path_name, "r")
try:
if self.text in f.read():
self.__found_flag = True
self.result.append(f'{self.text} found in {path_name}')
except UnicodeDecodeError:
print(f'解析错误 {path_name}')
```
### 封装`cmd`命令行接口
`click`模块封装命令行接口的标准用法,如下所示:
```python
@click.command()
@click.option('-t', help='要查找的文本')
@click.option('-p', help='在哪里查找')
def __cmd(t, p):
TextFinder(t, p).get_files()
if __name__ == "__main__":
cmd()
项目测试
截止今晚,2022年1月13日,未发现有bug
完整代码下载
上面完整py代码文件,可以在我的公众号后台回复:c,即可下载,同时后面的项目代码文件,我也会同步到这个文件夹中,下载方式也是回复c