10

我使用 Python 2.7.5 运行以下代码。在 Windows 下:

import os, shutil, stat, time

with open('test.txt', 'w') as f: pass # create an arbitrary file
shutil.copy('test.txt', 'test2.txt') # copy it
shutil.copystat('test.txt', 'test2.txt') # copy its stats, too

t1 = os.lstat('test.txt').st_mtime # get the time of last modification for both files
t2 = os.lstat('test2.txt').st_mtime

print t1 # prints something like: 1371123658.54
print t2 # prints the same string, as expected: 1371123658.54
print t1 == t2 # prints False! Why?!

我希望两个时间戳(=floats)是相等的(正如它们的字符串表示所暗示的那样),那么为什么t1 == t2评估为False

此外,我无法用更少的代码重现这种行为,即不比较os.lstat从两个不同文件中检索到的时间戳。我有一种感觉,我在这里遗漏了一些微不足道的东西......


编辑:经过进一步测试后,我注意到它确实偶尔打印True一次,但不会超过每 10 次运行一次。


编辑 2:正如 larsmans 所建议的:

print ("%.7f" % t1) # prints e.g. 1371126279.1365688
print ("%.7f" % t2) # prints e.g. 1371126279.1365681

这提出了两个新问题:

  1. 为什么调用后时间戳不相等shutil.copystat
  2. print轮次默认浮动?!
4

3 回答 3

7

copystat问题在于通话期间不同格式之间的转换。这是因为 Windows 以定点十进制格式存储文件时间,而 Python 以浮点二进制格式存储它们。因此,每次在两种格式之间进行转换时,都会损失一些准确性。通话期间copystat

  1. 调用os.stat将 Windows 格式转换为 Python 的浮点格式。失去了一些准确性。
  2. os.utime被调用来更新文件时间。这会将其转换回 Windows 格式。一些准确性再次丢失,并且文件时间不一定与第一个文件相同。

当您调用os.lstat自己时,会执行第三次不准确的转换。由于这些转换,文件时间并不完全相同。

文档os.utime提到了这一点:

请注意,您在此处设置的确切时间可能不会被后续的 stat() 调用返回,具体取决于您的操作系统记录访问和修改时间的分辨率


关于您的第二个问题(为什么print似乎两者都显示相同的值):将浮点值转换为带有str(f)print f将舍入该值的字符串。要获得保证对于不同浮点值唯一的值,请print repr(f)改用。

于 2013-06-13T12:53:34.937 回答
0
from decimal import *
print Decimal(t1)
print Decimal(t2)

对 t1 和 t2 使用 round()

于 2013-06-13T12:47:07.273 回答
-1

尝试打印浮点时差:print float.hex( t1 - t2)

结果:

0x1.0000000000000p-22
0x1.8000000000000p-21
0x0.0p+0
0x1.0000000000000p-20

我的 2cents 猜测:输出的变化来自浮点表示偏差和舍入误差。无论如何,在比较两个浮点数时,您应该始终使用 epsilon 值。

编辑:检查这个Python 错误

这是系统限制。底层文件系统支持文件戳的纳秒分辨率,stat(2) 也支持报告它们。但是,utimes(2) 在设置时只支持微秒分辨率。

在比较两个浮点数时,您最多只能使用微秒分辨率。

于 2013-06-13T12:43:43.997 回答