filecmp.cmp() 忽略不同的 os.stat() 签名?
Python 2 的文档中关于 filecmp()
这样写道:
除非给定 shallow 参数并且它为假,否则具有相同
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_atime
、st_mtime
和 st_ctime
——显然不相同,但 filecmp.cmp()
却显示这两个文件是相同的。我是不是理解错了,还是 filecmp.cmp()
的实现或文档有问题?
更新
Python 3 的 文档 已经重新表述,现在的内容是这样的,我认为这是一个改进,因为它更好地暗示了即使 shallow
为真,时间戳不同的文件仍然可能被认为是相等的。
如果 shallow 为真,具有相同
os.stat()
签名的文件会被认为是相等的。否则,将比较文件的内容。
顺便说一下,我觉得如果直接说成这样会更好:
如果 shallow 为真,只有在
os.stat()
签名不相等时才比较文件内容。
2 个回答
看起来自己动手做是得到想要结果的唯一办法。如果文档能写得更清楚一些,让普通读者也能明白这一点,那就太好了。
这是我现在正在使用的函数:
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)
你对文档的理解有些偏差。第二行说:
除非给定了shallow并且它是假的,否则具有相同
os.stat()
信息的文件被认为是相等的。
具有相同os.stat()
信息的文件被认为是相等的,但反过来说并不成立:具有不同os.stat()
信息的文件不一定被认为是不相等的。实际上,它们可能是不相等的,这种情况下就需要比较文件的实际内容。因为文件内容被发现是相同的,所以filecmp.cmp()
返回True
。
根据第三条,一旦确定文件是相等的,它会把这个结果缓存起来,如果你再次要求比较同样的文件,只要这些文件的os.stat
信息没有变化,它就不会再去读取文件内容了。