Question

I've came across a problem in python 2.7.1 (running on Mac OS X 10.7.5) with the os.utime command

I'm trying to develop a script that downloads files from an FTP that match certain criteria but if the file exists and I already have a copy of it on a local dir then I want to check file modification times. If they don't match then I download the new copy. To achieve this goal I get the FTP file modification time, convert it to timestamp and then use os.utime to change the access and modification dates of the files downloaded to match the FTP server ones. My problem is that as soon as I get out from the subroutine where I change the access and modification times they revert back to the original ones! I don't have anything running in background and I also tested the script on a linux server with the same results

If you run the code bellow twice it will show the problem in the debug comments as the files in the FTP server didn't change but the timestamps don't match the local ones that were correctly changed. Thanks in advance for any help in this problem.

import ftplib
import os
from datetime import datetime

def DownloadAndSetTimestamp(local_file,fi,nt):
    lf=open(local_file,'wb')
    f.retrbinary("RETR " + fi, lf.write, 8*1024)
    lf.close
    print fi + " downloaded!"

    print "-> mtime before change : " + str(os.stat(local_file).st_mtime)   
    print "-> atime before change : " + str(os.stat(local_file).st_atime)   
    print "-> FTP value     : " + str(int(nt))
    #set the modification time the same as server for future comparison
    os.utime(local_file,( int(nt) , int(nt) ))
    print "-> mtime after change  : "+ str(os.stat(local_file).st_mtime)
    print "-> atime after change  : "+ str(os.stat(local_file).st_atime)

print "Connecting to ftp.ncbi.nih.gov..."   
f=ftplib.FTP('ftp.ncbi.nih.gov')
f.login()
f.cwd('/genomes/Bacteria/')
listing=[]
dirs=f.nlst();
print "Connected and Dir list retrieved."

target_bug="Streptococcus_pseudopneumoniae"
print "Searching for :"+ target_bug
ct=0;
Target_dir="test/"
for item in dirs:
    if item.find(target_bug)>-1:
        print item
        #create the dir
        if not os.path.isdir(os.path.join(Target_dir,item)):
            print "Dir not found. Creating it..."
            os.makedirs(os.path.join(Target_dir,item))
        #Get the gbk 
        #1) change the dir
        f.cwd(item)
        #2) get *.gbk files in dir
        files=f.nlst('*.gbk')
        for fi in files:
            print "----------------------------------------------"
            local_file = os.path.join(Target_dir,item,fi)
            if os.path.isfile(local_file):
                print "################"
                print "File " + local_file + " already exists."
                #get remote modification time           
                mt = f.sendcmd('MDTM '+ fi)
                #converting to timestamp
                nt = datetime.strptime(mt[4:], "%Y%m%d%H%M%S").strftime("%s")
                #print "mtime FTP :" + str(int(mt[4:]))
                #print "FTP M timestamp   : " + str(nt)
                #print "Local M timestamp : " + str(os.stat(local_file).st_mtime)
                #print "Local A timestamp : " + str(os.stat(local_file).st_atime)

                if int(nt)==int(os.stat(local_file).st_mtime):
                    print fi +" not modified. Download skipped"
                else:
                    print "New version of "+fi
                    ct+=1
                    DownloadAndSetTimestamp(local_file,fi,nt)
                    print "NV Local M timestamp : " + str(os.stat(local_file).st_mtime)
                    print "NV Local A timestamp : " + str(os.stat(local_file).st_atime)
                print "################"

            else:
                print "################"
                print "New file: "+fi
                ct+=1
                mt = f.sendcmd('MDTM '+ fi)
                #converting to timestamp
                nt = datetime.strptime(mt[4:], "%Y%m%d%H%M%S").strftime("%s")
                DownloadAndSetTimestamp(local_file,fi,nt)
                print "################"

        f.cwd('..')
f.quit()
print "# of "+target_bug+" new files found and downloaded: " + str(ct)
Was it helpful?

Solution

You're missing the parentheses in lf.close; it should be lf.close().

Without the parentheses, you're effectively not closing the file. Instead, the file is closed a bit later by the garbage collector after your call to os.utime. Since closing a file flushes the outstanding IO buffer contents, modification time will be updated as a side effect, clobbering the value you previously set.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top