跳转至

🔥AI副业赚钱星球

点击下面图片查看

郭震AI

项目环境

编辑日期: 2024-11-28 文章阅读:

这是第五个Python小项目,做一个文件定位器。 查找某目录下所有文件,包含指定查找串的文件。注意,这里不仅仅匹配文件名,而是搜索文件的内容。 为了加快搜索速度,本身这又是一个IO任务,所以选用至多同时存活500个线程的技术,加快搜索进度。

项目环境

使用osthreading内置模块,用于操作目录和文件,多线程相关。

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

长按关注,回复c

京ICP备20031037号-1