Python 2.5.1 broken os.stat module

Joe Salmeri JoeSalmeri at hotmail.com
Thu May 31 20:26:11 EDT 2007


Hi Tony,

I still believe there is a problem.

I was searching for os.stat problems so I hadn't seen that one yet. (THANKS)

I just read that thread but it seems that the conclusion was that this was a 
bug in a Microsoft c runtime library.

Here's why I think there is still a problem:

I created a file and specifically set the created date, last accessed date 
and last write date to

    01/02/2003 12:34:56

After setting the date and time on the file I verified the following:

The dir /tc command shows the correct Create date of 01/02/2003 12:34
The dir /ta command shows the correct Access date of 01/02/2003 12:34
The dir /tw command shows the correct Write date of 01/02/2003 12:34

Looking at the properties of the file in Windows Explorer also shows that 
all 3 dates match.

When Python 2.4.2 os.stat is used to get those timestamps all 3 are CORRECT

When Python 2.5.1 os.stat is used to get those timestamps all 3 are WRONG 
and they are off by exact 1 hour

    01/02/2003 11:34:56 instead of 01/02/2003 12:34:56

In the case of my above test I know exactly what the timestamp on the file 
is because I manually set it so that all 3 timestamps are the same.
Since Python 2.5.1 does not return the known values for that files 
timestamps how can it not be a Python 2.5.1 bug?

Further testing shows that the results are somewhat inconsistent, many times 
the create and access date are correct but the Last Write timestamp is 
wrong.  It is generally off by one hour but I have seen situations where it 
was +1 hour and other situations where it was -1 hour.

I even found situations where the python timestamp was 1 minute later.  (I 
know about the 2 second timestamps on FAT, all my filesystems are NTFS).  I 
just found a situation where the python timestamp was 02:51 PM and the 
windows timestamp was 02:12 PM.   DST or timezone changes are not going to 
make the results be off by 39 minutes?   (My timezone is GMT - 5:00).

As an additional test I wrote the following Python program which takes a 
directory name as a paramater.
It retrieves all 3 dates for all files in all directories and subdirectories 
for the specified directory name.
First it gets the dates using Python and os.stat, then it runs the dir /tc, 
dir /ta, and dir /tw commands on the file.
Finally it compares the dates and times returned by Python against the dates 
and times that the Windows dir command is reporting.

If you run the program using Python 2.4.2 then ALL dates and times returned 
by Python 2.4.2 correctly match the dates and times that Windows reports.

If you run the program using Python 2.5.1 against the same directory then 
you get intermittient results.

As a quick test I ran it against a directory on my home directory.

Python 2.4.2 all dates matched between what the Windows dir command reported 
and what Python 2.4.2 reported.

Python 2.5.1 had the following differences (more than 50% of the time it was 
wrong)

Total Files Processed    : 149

Matched All 3 Dates      : 70
Did NOT Match All 3 Dates: 79

Matched Create Date      : 69
Did NOT Match Create Date: 10

Matched Access Date      : 59
Did NOT Match Access Date: 20

Matched Write Date       : 11
Did NOT Match Write Date : 68

Here's the source for the check_dates.py program.  Run it for youself and 
see what your results are.

import os
import stat
import sys
import time

if len(sys.argv) == 1:
    print
    print '%s path_to_check' % (sys.argv[0])
    print
    raise SystemExit
else:
    path_to_check       = sys.argv[1]

file_count              = 0

file_match_count        = 0
file_no_match_count     = 0

create_match_count      = 0
create_no_match_count   = 0

access_match_count      = 0
access_no_match_count   = 0

write_match_count       = 0
write_no_match_count    = 0

for root, dirs, files in os.walk(r'%s' % path_to_check):
    for file in files:
        file_count      = file_count + 1
        file_name       = os.path.join(root, file)

        create_ts_match = False
        access_ts_match = False
        write_ts_match  = False

        file_stats  = os.stat(file_name)

        python_create_ts    = time.strftime('%m/%d/%Y  %I:%M %p', 
time.localtime(file_stats[stat.ST_CTIME]))
        python_access_ts    = time.strftime('%m/%d/%Y  %I:%M %p', 
time.localtime(file_stats[stat.ST_ATIME]))
        python_write_ts     = time.strftime('%m/%d/%Y  %I:%M %p', 
time.localtime(file_stats[stat.ST_MTIME]))

        win_create_ts       = os.popen('dir /a /tc "%s"' % 
(file_name)).readlines()[5][0:20]
        win_access_ts       = os.popen('dir /a /ta "%s"' % 
(file_name)).readlines()[5][0:20]
        win_write_ts        = os.popen('dir /a /tw "%s"' % 
(file_name)).readlines()[5][0:20]

        if python_create_ts == win_create_ts:   create_ts_match = True
        if python_access_ts == win_access_ts:   access_ts_match = True
        if python_write_ts  == win_write_ts:    write_ts_match  = True

        if create_ts_match and access_ts_match and write_ts_match:
            # All timestamps match
            file_match_count            = file_match_count + 1
        else:
            file_no_match_count         = file_no_match_count + 1
            print
            print 'File Name       : %s' % (file_name)
            print

            if create_ts_match:
                create_match_count      = create_match_count + 1
            else:
                create_no_match_count   = create_no_match_count + 1

                print 'python_create_ts: %s' % (python_create_ts)
                print 'win_create_ts   : %s' % (win_create_ts)
                print

            if access_ts_match:
                access_match_count      = access_match_count + 1
            else:
                access_no_match_count   = access_no_match_count + 1

                print 'python_access_ts: %s' % (python_access_ts)
                print 'win_access_ts   : %s' % (win_access_ts)
                print

            if write_ts_match:
                write_match_count       = write_match_count + 1
            else:
                write_no_match_count    = write_no_match_count + 1

                print 'python_write_ts : %s' % (python_write_ts)
                print 'win_write_ts    : %s' % (win_write_ts)
                print

#
# Show Count Results
#

print 'Total Files Processed    : %s' % (file_count)
print
print 'Matched All 3 Dates      : %s' % (file_match_count)
print 'Did NOT Match All 3 Dates: %s' % (file_no_match_count)
print
print 'Matched Create Date      : %s' % (create_match_count)
print 'Did NOT Match Create Date: %s' % (create_no_match_count)
print
print 'Matched Access Date      : %s' % (access_match_count)
print 'Did NOT Match Access Date: %s' % (access_no_match_count)
print
print 'Matched Write Date       : %s' % (write_match_count)
print 'Did NOT Match Write Date : %s' % (write_no_match_count)
print







"Tony Meyer" <tony.meyer at gmail.com> wrote in message 
news:1180648618.295955.68600 at x35g2000prf.googlegroups.com...
> On Jun 1, 9:16 am, "Joe Salmeri" <JoeSalm... at hotmail.com> wrote:
>> I just upgraded from Python 2.4.2 to Python 2.5.1 and have found some
>> unexpected behavior that appears to be a bug in the os.stat module.
>
> Have you read this thread?
>
> http://groups.google.com/group/comp.lang.python/browse_thread/thread/890eef2197c6f045/5466283a8253cafb?lnk=gst&q=getmtime&rnum=3#5466283a8253cafb
>
> I suspect that it explains your problem.
>
> Cheers,
> Tony
> 





More information about the Python-list mailing list