0

私はAWS S3ファイルにアクセスするためにPython botoモジュールを使用しています。 UNLOADコマンドでRedshiftからファイルをアンロードし、ファイルが自動的にgzipされます。 Redshiftは1つのファイルの10の部分を生成します。AWS S3ファイルをpython botoでダウンロードすると、ファイルが存在するにもかかわらず404が返されます

これは私がファイルリストを取得し、ダウンロード機能を呼び出すために使用したコードの一部です:

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") 

問題はそれが、時々ありますAWSは404エラーを返しますが、ファイルは存在しません。私は手動で、S3バケットのファイルapperasをチェックして、それはデータを持っています。 私は、変更が伝播されていない場合、S3がそのようなエラーを返す可能性があることを読んだことがあります。そのため、ダウンロード機能はこのようになります。ファイルにエラーが発生した場合は、同じファイルを再度ダウンロードしようとします。問題は、ファイルを2回目にダウンロードすると空になり、一部のデータが失われることです。 (その10分の1)。

この問題は、さまざまなバケットとフォルダでランダムに発生します。

+0

もう一つの選択肢は、[AWSコマンドラインインターフェイス(CLI)](http://aws.amazon.com/cli/)を使用して、 'aws s3 sync'または' aws s3 cp- -recursive'コマンドを使用します。 –

+0

私はダウンロード機能の中でそれを使うことができましたが、それは404エラーを解決できると思いますか?私が考えたことは、Pythonではなく、AWS側でエラーが発生することです。 – quickshare

答えて

0

私は、ダウンロード機能の仕方を変えることで解決することができました。私はそこから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 

、私は、ファイルのいずれかが何らかの理由でダウンロードに失敗した場合、私は問題があったということを示す1にerror_cntを設定しますことを確認することができます。その後、システムエラーを投げてプロセス全体に失敗する前に、フォルダ全体を3回再度ダウンロードしようとする機能があります。

関連する問題