3 个稳定版本

2.5.1 2024年4月1日
2.5.0 2024年3月22日
2.4.2 2024年3月15日

1059文件系统

Download history 2/week @ 2024-05-29

每月下载量 137

MIT 和 CC-PDDC 许可证

115KB
3K SLoC

scandir-rs

scandir_rs 是一个类似于 os.walk() 的目录迭代模块,但具有更多功能和更高的速度。根据函数调用,它返回路径列表、按条目类型分组的列表元组或包含文件类型和状态信息以及名称的 DirEntry 对象。使用 scandir_rs 的速度比 os.walk()2-17 倍(取决于平台、文件系统和文件树结构),通过在后台并行化迭代。

如果您只对目录统计信息感兴趣,可以使用 Count

scandir_rs 包含以下类

  • Count 用于确定目录的统计信息。
  • Walk 用于获取目录条目的名称。
  • Scandir 用于获取目录条目的详细信息。

有关 API,请参阅

安装

要从源代码构建此 wheel,您需要工具 maturin

安装 maturin

cargo install maturin

重要提示:为了构建此项目,至少需要 Rust 版本 1.61!

构建 wheel(Windows 上不可用)

maturin build --release --strip

在 Windows 上构建 wheel

maturin build --release --strip --no-sdist

maturin 将为您的系统上安装的所有 Python 版本构建 wheel。

为不同版本的 Python 构建和运行测试

为了更容易地为多个不同的 Python 版本构建 wheel,已添加脚本 build_wheels.sh。它为 Python 版本 3.7、3.8、3.9、3.10 和 3.11 创建 wheel。此外,它在每个 wheel 成功创建后运行 pytest

有关安装 pyenv 的说明,请参阅 此处

示例

获取目录的统计信息

from scandir_rs import Count, ReturnType

print(Count("/usr", return_type=ReturnType.Ext).collect())

collect 方法释放 GIL。因此,其他 Python 线程可以并行运行。

同样,但使用类实例在后台异步运行

from scandir_rs import Count, ReturnType

instance = Count("/usr", return_type=ReturnType.Ext))
instance.start())  # Start scanning the directory
...
values = instance.results()  # Returns the current statistics. Can be read at any time
...
if instance.busy():  # Check if the task is still running.
...
instance.stop()  # If you want to cancel the task
...
instance.join()  # Wait for the instance to finish.

以及使用上下文管理器

import time

from scandir_rs import Count, ReturnType

with Count("/usr", return_type=ReturnType.Ext) as instance:
    while instance.busy():
        statistics = instance.results()
        # Do something
        time.sleep(0.01)
    print(instance.results())

os.walk() 示例

from scandir_rs import Walk

for root, dirs, files in Walk("/usr"):
    # Do something

带有扩展数据

from scandir_rs import Walk, ReturnType

for root, dirs, files, symlinks, other, errors in Walk("/usr", return_type=ReturnType.Ext):
    # Do something

os.scandir() 示例

from scandir_rs import Scandir, ReturnType

for path, entry in Scandir("~/workspace", return_type=ReturnType.Ext):
    # entry is a custom DirEntry object

基准测试

examples/benchmark.py

在下表中,Walk.iter 返回与 os.walk 相当的结果。

Linux Ryzen 5 2400G 和 SSD

目录 /usr

  • 110171 个目录
  • 862634 个文件
  • 47804 个符号链接
  • 12275 个硬链接
  • 12 个设备
  • 0 个管道
  • 32.7GB 大小和 34.8GB 磁盘使用量
时间 [秒] 方法
3.450 os.walk (Python 3.10)
6.021 scantree (Python 3.10)
1.186 Count.collect
1.416 Count(ReturnType=Ext).collect
1.089 Walk.iter
1.350 Walk.collect
1.336 Walk(ReturnType=Ext).collect
2.232 Scandir.collect
1.839 Scandir.iter
2.437 Scandir(ReturnType=Ext).collect

在 Linux 上大约 ~3 倍更快(与 os.walk 相比,Walk.iter)。

Windows 10,搭载 Core i7-4810MQ @ 2.8GHz 笔记本电脑,MTF SSD

目录 C:\Windows

  • 132604 个目录
  • 349911 个文件
  • 44.4GB 大小和 45.2GB 磁盘使用量
时间 [秒] 方法
21.779 os.walk (Python 3.10)
13.085 scantree (Python 3.10)
3.257 Count.collect
16.605 Count(ReturnType=Ext).collect
4.102 Walk.iter
4.056 Walk.collect
4.190 Walk(ReturnType=Ext).collect
3.993 Scandir.collect
8.921 Scandir.iter
17.616 Scandir(ReturnType=Ext).collect

在 Windows 10 上大约 ~5.3 倍更快(与 os.walk 相比,Walk.iter)。

目录 linux-5.9

  • 4711 个目录
  • 69973 个文件
  • 1.08GB 大小和 1.23GB 磁盘使用量
时间 [秒] 方法
0.411 os.walk (Python 3.10)
1.203 os.walk (stat)
0.218 scandir.Count()
0.278 scandir.Count(return_type=ReturnType.Ext).collect()
0.227 scandir_rs.Walk().collect()
0.164 scandir.Walk(return_type=scandir.ReturnType.Ext) (iter)
0.204 scandir.Walk(return_type=scandir.ReturnType.Ext) (collect)
0.350 scandir.Scandir(return_type=ReturnType.Base).collect()
0.426 scandir.Scandir(return_type=ReturnType.Ext).collect()

在 Linux 上大约 ~2.5 倍更快(与 os.walk 相比,Walk.iter)。

时间 [秒] 方法
1.998 os.walk (Python 3.10)
14.875 os.walk (stat)
0.278 scandir.Count()
2.114 scandir.Count(return_type=ReturnType.Ext).collect()
0.464 scandir_rs.Walk().collect()
0.313 scandir.Walk(return_type=scandir.ReturnType.Ext) (iter)
0.455 scandir.Walk(return_type=scandir.ReturnType.Ext) (collect)
0.624 scandir.Scandir(return_type=ReturnType.Base).collect()
2.409 scandir.Scandir(return_type=ReturnType.Ext).collect()

在 Windows 10 上大约 ~6.4 倍更快(与 os.walk 相比,Walk.iter)。

依赖项

~6–12MB
~138K SLoC