我正在尝试从FTP服务器下载某个文件(名为010010-99999-year.gz)。同一个文件,但不同年份存在于不同的FTP目录中。例如:
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 等等。图片说明了其中一个目录:
该文件不在所有目录中(即所有年份)。在这种情况下,我希望脚本忽略丢失的文件,打印“不可用”,并继续下一个目录(即明年)。 我可以使用NLST列表,首先生成当前FTP目录中的文件列表,然后检查我的文件是否在该列表上,但这很慢,NOAA(拥有服务器的组织)不喜欢文件列表(source)。因此我提出了这个代码:
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()
这会正确下载现有文件(1973 - 2014年),但它也会在1901 - 1972年间生成空文件。该文件不在1901-1972的FTP中。 我在使用try和其他问题时做错了什么,还是其他问题?
答案 0 :(得分:2)
我拿了你的代码并对其进行了一些修改:
from ftplib import FTP, error_perm
import os
def FtpDownloader2(url="ftp.ncdc.noaa.gov"):
ftp = FTP(url)
ftp.login()
for year in range(1901, 2015):
remote_file = '/pub/data/noaa/isd-lite/{0}/010010-99999-{0}.gz'.format(year)
local_file = os.path.basename(remote_file)
try:
with open(local_file, "wb") as file_handle:
ftp.retrbinary('RETR %s' % remote_file, file_handle.write)
print('OK', local_file)
except error_perm:
print('ERR', local_file)
os.unlink(local_file)
ftp.close()
except
子句。这种类型的构造将忽略所有错误,使其难以排除故障。为解决此问题,我添加了特定的例外error_perm
with
语句保证error_perm
异常,我删除了本地文件,表明该文件无法从服务器获取cwd
两次会导致进程变慢range(1901, 2015)
将不包括2015年。如果您需要,则必须指定range(1901, 2016)
此更新回答了有关不创建空本地文件(然后必须删除它们)的问题。有几种不同的方式:
答案 1 :(得分:1)
我认为问题出在你的尝试中:除了块,你在检查文件是否存在之前保持文件处理程序为新文件打开:
try:
file=open(fullStationId,"wb")
ftp.retrbinary('RETR %s' % fullStationId, file.write)
print("File is available")
file.close()
except:
print("File not available")
相反,在except块中添加一个额外的语句来关闭文件处理程序,另一个语句删除文件,如果它是空的。
另一种可能性是,只有当文件存在并且使用ftp.size
在服务器上具有非零大小时才打开本地写入文件