I am trying to download a certain file (named 010010-99999-year.gz) from an FTP server. This same file, but for different years is residing in different FTP directories. For instance:
ftp://ftp.ncdc.noaa.gov/pub/data/noaa/isd-lite/2000/010010-99999-1973.gz ftp://ftp.ncdc.noaa.gov/pub/data/noaa/isd-lite/2001/010010-99999-1974.gz and so on. The picture illustrates one of the directories:
The file is not located in all the directories (i.e. all years). In such case I want the script to ignore that missing files, print "not available", and continue with the next directory (i.e. next year). I could do this using the NLST listing by first generating a list of files in the current FTP directory and then checking if my file is on that list, but that is slow, and NOAA (the organization owning the server) does not like file listing (source). Therefore I came up with this code:
def FtpDownloader2(url="ftp.ncdc.noaa.gov"):
ftp=FTP(url)
ftp.login()
for year in range(1901,2015):
ftp.cwd("/pub/data/noaa/isd-lite")
ftp.cwd(str(year))
fullStationId="010010-99999-%s.gz" % year
try:
file=open(fullStationId,"wb")
ftp.retrbinary('RETR %s' % fullStationId, file.write)
print("File is available")
file.close()
except:
print("File not available")
ftp.close()
This downloads the existing files (year 1973-2014) correctly, but it is also generating empty files for years 1901-1972. The file is not in the FTP for 1901-1972. Am I doing anything wrong in the use of try and except, or is it some other issue?
I took your code and modified it a little:
Notes
except
clause without a specific exception class. This type of construct will ignore all errors, making it hard to troubleshoot. To fix this, I added the specific exceptionerror_perm
with
statement guarantees thaterror_perm
exception occurred, a sign that the file is not available from the servercwd
twice which slows down the processrange(1901, 2015)
will not include 2015. If you want it, you have to specifyrange(1901, 2016)
Update
This update answers your question regarding not creating empty local file (then having to delete them). There are a couple of different ways:
I think the problem is within your try: except block, where you keep a file handler open for a new file before checking if the file exists or not:
Instead, add an additional statement in the except block to close the file handler, and another statement to remove the file if it is empty.
Another possibility is to open the file for writing locally only if the file exists and has a non zero size on the server using
ftp.size