filecmp.cmp()是否忽略不同的os.stat()签名?

7

Python 2文档中filecmp()的说明如下:

除非给定并且为假,否则具有相同os.stat()签名的文件被视为相等。

这听起来像是两个文件除了它们的os.stat()签名不同会被认为是不相等的,但是事实并非如此,正如运行以下代码片段所示:

import filecmp
import os
import shutil
import time

with open('test_file_1', 'w') as f:
    f.write('file contents')
shutil.copy('test_file_1', 'test_file_2')
time.sleep(5)  # pause to get a different time-stamp
os.utime('test_file_2', None)  # change copied file's time-stamp

print 'test_file_1:', os.stat('test_file_1')
print 'test_file_2:', os.stat('test_file_2')
print 'filecmp.cmp():', filecmp.cmp('test_file_1', 'test_file_2')

输出:

test_file_1: nt.stat_result(st_mode=33206, st_ino=0L, st_dev=0, st_nlink=0,
  st_uid=0, st_gid=0, st_size=13L, st_atime=1320719522L, st_mtime=1320720444L, 
  st_ctime=1320719522L)
test_file_2: nt.stat_result(st_mode=33206, st_ino=0L, st_dev=0, st_nlink=0, 
  st_uid=0, st_gid=0, st_size=13L, st_atime=1320720504L, st_mtime=1320720504L, 
  st_ctime=1320719539L)
filecmp.cmp(): True

正如您所看到的,这两个文件的时间戳——st_atimest_mtimest_ctime——显然不同,但是filecmp.cmp()表明这两个文件相同。我是否有什么误解,或者filecmp.cmp()的实现或文档中存在缺陷?
更新
Python 3 documentation已经重新表述,目前说的是以下内容,仅在更好地暗示浅层比较为真时可能认为具有不同时间戳的文件仍相等。
如果shallow为真,则具有相同os.stat()签名的文件被视为相等。否则,比较文件的内容。
FWIW,我认为最好直接说这样的话:
如果shallow为true,则仅在os.stat()签名不相同时比较文件内容。
2个回答

8
你误解了文档。第二行说:
除非给出shallow并且为false,否则具有相同os.stat()签名的文件被视为相等。
具有相同os.stat()签名的文件被视为相等,但逻辑反向不成立:具有不同os.stat()签名的文件不一定被视为不相等。相反,它们可能不相等,在这种情况下会比较实际文件内容。由于发现文件内容相同,filecmp.cmp()返回True
根据第三条款,一旦确定文件相等,它将缓存该结果,如果您再次要求比较相同的文件,则不会重新读取文件内容,只要这些文件的os.stat结构不改变

是的,我假设第二行的逻辑反义应该是正确的。谢谢。是否有Python内置函数可以将它们视为不相等,还是必须自己编写? - martineau
在查找并检查 filecmp.py 代码后,我现在可以清楚地看到 cmp() 的作用了 - 我认为这与文档不一致。当给定(或默认)一个真值时,shallow 没有被尊重,因为文件只有在它们的 os.stat() 签名匹配时才会被读取。在我看来,如果 shallow 是真的,它们的内容就不应该被比较,而只考虑它们的签名 - 这是文档所说和我所需要的行为。 - martineau

1
似乎“自己编写”确实是产生理想结果所必需的。只要文档清晰明了,让一般读者得出这个结论就好了。
这是我目前正在使用的函数:
def cmp_stat_weak(a, b):
    sa = os.stat(a)
    sb = os.stat(b)
    return (sa.st_size == sb.st_size and sa.st_mtime == sb.st_mtime)

是的,这就是我认为filecmp.cmp()会使用其shallow选项进行比较的类型,但如何实现并不是我的问题——而且创建一个替代函数的投入要比这更复杂。此外,我不认为自己是“随意读者”,因为我对文档的浏览方式并不肤浅或表面,相反,它是完全相反的。“典型”的形容词可能更好一些。 - martineau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接