使用python boto下载AWS S3文件将返回404,即使该文件存在

使用python boto下载AWS S3文件将返回404,即使该文件存在,python,amazon-web-services,amazon-s3,http-status-code-404,boto,Python,Amazon Web Services,Amazon S3,Http Status Code 404,Boto,我正在使用Python boto模块访问AWS S3文件。 我用unload命令从Redshift卸载文件,文件会自动gzip。红移生成一个文件的10个部分 这是我用来获取文件列表并调用下载函数的代码部分: key_list = bucket.list('folder_on_the_bucket') pool = ThreadPool(processes=10) partial_download = partial(download,0) pool.map(partial_download, k

我正在使用Python boto模块访问AWS S3文件。 我用unload命令从Redshift卸载文件,文件会自动gzip。红移生成一个文件的10个部分

这是我用来获取文件列表并调用下载函数的代码部分:

key_list = bucket.list('folder_on_the_bucket')
pool = ThreadPool(processes=10)
partial_download = partial(download,0)
pool.map(partial_download, key_list)
def download(retry_cnt,key):
retry_cnt = retry_cnt
key = key
try:
    #make sure that I download only files, not folders
    if key.name[-1]=='/' or key.name[-1]=='\\':
        pass
    else:
        log.info("Downloading %s" % local_dir+ntpath.basename(key.name))
        key.get_contents_to_filename(local_dir+ntpath.basename(key.name))
        if retry_cnt > 0:
            #copy all files that needed to be retried to a specific directory (for debugging purposes)
            shutil.copyfile(local_dir+ntpath.basename(key.name), 'error_files_folder'+ntpath.basename(key.name))
except:
    if retry_cnt < 3:
        retry_cnt += 1
        log.warning("error downloading file %s, retrying for the %s. time" % (str(key.name),str(retry_cnt)))
        log.warning(str(sys.exc_info()[1]))
        time.sleep(5)
        download(retry_cnt,key)
    else:
        log.error(sys.exc_info()[1])
        sys.exit("Unable to download file")
这是下载功能:

key_list = bucket.list('folder_on_the_bucket')
pool = ThreadPool(processes=10)
partial_download = partial(download,0)
pool.map(partial_download, key_list)
def download(retry_cnt,key):
retry_cnt = retry_cnt
key = key
try:
    #make sure that I download only files, not folders
    if key.name[-1]=='/' or key.name[-1]=='\\':
        pass
    else:
        log.info("Downloading %s" % local_dir+ntpath.basename(key.name))
        key.get_contents_to_filename(local_dir+ntpath.basename(key.name))
        if retry_cnt > 0:
            #copy all files that needed to be retried to a specific directory (for debugging purposes)
            shutil.copyfile(local_dir+ntpath.basename(key.name), 'error_files_folder'+ntpath.basename(key.name))
except:
    if retry_cnt < 3:
        retry_cnt += 1
        log.warning("error downloading file %s, retrying for the %s. time" % (str(key.name),str(retry_cnt)))
        log.warning(str(sys.exc_info()[1]))
        time.sleep(5)
        download(retry_cnt,key)
    else:
        log.error(sys.exc_info()[1])
        sys.exit("Unable to download file")
def下载(重试,按键):
重试\u cnt=重试\u cnt
钥匙
尝试:
#确保我只下载文件,不下载文件夹
如果key.name[-1]='/'或key.name[-1]='\\':
通过
其他:
log.info(“正在下载%s”%local_dir+ntpath.basename(key.name))
key.get_contents_to_filename(local_dir+ntpath.basename(key.name))
如果重试\u cnt>0:
#将需要重试的所有文件复制到特定目录(用于调试目的)
shutil.copyfile(local\u dir+ntpath.basename(key.name),“error\u files\u folder”+ntpath.basename(key.name))
除:
如果重试\u cnt<3:
重试\u cnt+=1
log.warning(“下载文件%s时出错,重试时间为%s%”(str(key.name),str(retry_cnt)))
日志警告(str(sys.exc_info()[1]))
时间。睡眠(5)
下载(重试,密钥)
其他:
日志错误(sys.exc_info()[1])
sys.exit(“无法下载文件”)
问题是,有时,AWS会返回404错误,文件不存在。我已经手动检查过了,文件出现在S3 bucket中,它有数据。 我已经读到,如果没有传播更改,S3可能会返回这样的错误。这就是下载函数看起来像这样的原因。如果文件出现错误,我将再次尝试下载相同的文件。问题是,我第二次下载文件时,它是空的,我丢失了一些数据。(十分之一)


此问题随机出现在不同的存储桶和文件夹上

我通过改变下载功能的工作方式,设法解决了这个问题。我从那里删除了try,并将其设置在调用它的代码部分

def get_download_files():
    global key_list
    key_list = bucket.list(s3_full_path)
    for f in key_list:
        log.info(f)
    try:
        pool = ThreadPool(processes=10)
        pool.map(download, key_list)
    except:
        log.warning("error occured while downloading")
        log.warning(sys.exc_info()[1])
        global error_cnt
        error_cnt = 1
        pass

通过使用此函数,我可以确保如果任何文件由于任何原因无法下载,我会将error_cnt设置为1,表示出现了问题。之后,我有一个函数,在抛出系统错误并使整个过程失败之前,再次重试下载整个文件夹三次

另一个选项是使用aws s3 sync或aws s3 cp--recursive命令来下载文件。我可以在下载函数中使用它,但您认为它可以解决404错误吗?我认为错误发生在AWS端,而不是Python端。