为什么即使'shallow'参数为True,filecmp.cmp对于大文件仍然很慢?

0 投票
1 回答
1785 浏览
提问于 2025-04-18 03:34

我写了一个Python脚本,用来比较两个文件夹里的文件,使用的是filecmp.cmp这个功能。这个脚本能正常工作,但我刚刚尝试对一堆很大的文件进行比较时,速度非常慢。

文档上说,当shallow参数为真(默认就是这样),filecmp.cmp只会比较os.stat的结果。

不过,我发现对于另一组大的jpg文件,脚本运行得快多了。我在想,文件大小对速度的影响怎么比文件数量大,就好像它只检查os.stat一样。

1 个回答

3

我觉得关于 shallow 参数的说明有点误导人。传入 shallow = True 并不一定会阻止 filecmp.cmp 函数比较文件的内容。如果你的文件大小相同但修改时间 mtime 不同,它们的内容还是会被检查。

你可以在你的 Python 安装中查看 cmp 的实现,或者在这个 Python 源代码库 中查看当前的源代码。

这里是 cmp 的相关部分:

def cmp(f1, f2, shallow=True):
    # long docstring removed

    s1 = _sig(os.stat(f1))
    s2 = _sig(os.stat(f2))
    if s1[0] != stat.S_IFREG or s2[0] != stat.S_IFREG:
        return False
    if shallow and s1 == s2:
        return True
    if s1[1] != s2[1]:
        return False

    # rest of function, which calls a helper to do the actual file contents comparisons

_sig 这个辅助函数会返回一个元组,里面包含从文件的 stat 数据结构中提取的值。这个元组的值包括文件类型、文件大小和它的 mtime(通常是文件内容最后一次修改的时间)。

我在代码片段中包含的测试是为了快速判断两个文件是否相同,主要依据这些元数据。如果其中一个文件不是“常规”文件(比如是目录或者特殊的系统文件),那么它们就被认为是不相等的。此外,如果它们的大小不一样,那肯定也不相等。

shallow 参数的作用是允许快速的正向测试。如果 shallow 为真,并且两个文件的大小和 mtime 相同,filecmp.cmp 就会认为这两个文件是相等的。

我怀疑在你的程序中发生的情况是,你当前目录下有很多文件大小完全相同(可能是因为内容非常相似,或者因为文件大小是由数据格式决定的)。而你之前的数据集没有那么多相同大小的文件,所以你的代码能够快速排除它们。

* 我觉得 filecmp.cmp 的文档说明非常误导,甚至可以说是个 bug(要么是因为没有正确描述行为,要么是实际实现有问题,应该修正以符合文档)。看起来我并不是唯一这么认为的人。这里有一个关于这个问题的 bug 报告,不过已经好几年没有更新了。我会在这个 bug 上加个链接到这个问题,也许会有人来修复它!

撰写回答