0

I was playing around with os.utime() in Python, and have encountered a curiosity: If I read the mtime (last modified time) from a file, update the file with the same value I've read, and re-read the value, I get different values, as demonstrated here:

#!/usr/bin/python

import os

FN = "tmp_file.txt"
with open(FN, 'w') as the_file:
    the_file.write("hello\n")

t1 = os.path.getmtime(FN)
os.utime(FN, (t1, t1))
t2 = os.path.getmtime(FN)

print "mtime before: %.10f" % t1
print "mtime after:  %.10f" % t2
print t1 == t2
print t2 - t1

If I run this, output looks like:

mtime before: 1502410779.6215209961
mtime after:  1502410779.6215200424
False
-9.53674316406e-07

But it's not completely random. It looks like there are maybe ~5 possible outcomes, including perfect equality.

I would think this is just a straight-up "write" as-is, so I don't expect floating point arithmetic to mess things up. What's happening here?

user2671688
  • 643
  • 1
  • 6
  • 13
  • For what it's worth, I just ran it on Python 2.7.13 and 3.5.3. On Python 2 I get the same result as you, but on Python 3 the value is exactly the same. – Paulo Almeida Aug 11 '17 at 00:50
  • Good observation! I tried, and you're right, it works consistently in 3, while breaking in 2.7. – user2671688 Aug 11 '17 at 02:29
  • The docs do say this: "Note The exact meaning and resolution of the st_atime, st_mtime, and st_ctime attributes depend on the operating system and the file system. For example, on Windows systems using the FAT or FAT32 file systems, st_mtime has 2-second resolution, and st_atime has only 1-day resolution. See your operating system documentation for details." It's likely also just imprecision caused by converting the internal way the file system stores time. I do wonder why this isn't an issue in Python3 though. – user2671688 Aug 12 '17 at 02:07
  • Ok, you got me curious enough to do a quick check. In Python 3 `os.utime` can take an `ns` argument for times expressed in nanoseconds, and although I didn't check in detail, the code for [Python 2](https://github.com/python/cpython/blob/2.7/Modules/posixmodule.c) and [Python 3](https://github.com/python/cpython/blob/master/Modules/posixmodule.c) versions of utime differs in the way they deal with nanoseconds. I suppose the reason for that is the evolution of clocks, as you can see in [an answer to a previous question at Stack Overflow](https://stackoverflow.com/a/38454199/1081569). – Paulo Almeida Aug 12 '17 at 19:01
  • I think I read somewhere while digging, that Python 3 stores NS in a separate field, which may be a huge contributing factor to the difference. In fact, looking at those code links, you can see the separate field in: stat_result_fields[] – user2671688 Aug 12 '17 at 22:40
  • Yes, and I also read a couple of interesting issues: [one about adding nanoseconds to `utime` and others](http://bugs.python.org/issue14127) and [a current one about supporting nanoseconds in datetime](https://bugs.python.org/issue15443). The latter was particularly interesting because of the use cases (1G and 10G network data, stock markets, GPS clocks). I had no idea this discussion was going on. Anyway, I'm not going to really answer the question of where exactly the difference comes from, and it didn't attract any more attention. My curiosity is satisfied :) – Paulo Almeida Aug 13 '17 at 02:30

0 Answers0