S3からファイル一覧を取得し、直近2hのファイルを対象にダウンロードする処理をboto3で書きました。
これをboto2で書く必要にせまられましたが、検索してもboto3の情報ばかりで苦労したのでメモしておきます。
boto3版
# -*- coding: utf-8 -*-
import os
import boto3
import pytz
from datetime import datetime, timedelta
s3_bucket_name = os.getenv('AWS_S3_BUCKET_NAME')
s3 = boto3.client(
's3',
aws_access_key_id=os.getenv('AWS_S3_ACCESS_KEY_ID'),
aws_secret_access_key=os.getenv('AWS_S3_SECRET_ACCESS_KEY')
)
# 直近2h以内に更新されたファイルを対象に取得する
def download_new_files(minutes=120):
utc_now = datetime.now(pytz.timezone('utc')) - timedelta(minutes=minutes)
prefix = 'baseball/'
res = list_handler(prefix)
# 日付降順にsort
res_sorted = sorted(res, key=lambda x: x['LastModified'], reverse=True)
download_path = '/var/tmp/'
if not os.path.isdir(download_path + prefix):
os.mkdir(download_path + prefix)
for content in res_sorted:
if content['LastModified'] < utc_now:
break
s3.download_file(s3_bucket_name, content['Key'], download_path + content['Key'])
print(content['Key'] + ' download complete.')
# 1000件を超える場合の考慮
def list_handler(prefix):
contents = []
next_token = ''
while True:
if next_token == '':
response = s3.list_objects_v2(Bucket=s3_bucket_name, Prefix=prefix)
else:
response = s3.list_objects_v2(Bucket=s3_bucket_name, Prefix=prefix, ContinuationToken=next_token)
contents.extend(response['Contents'])
if 'NextContinuationToken' in response:
next_token = response['NextContinuationToken']
else:
break
return contents
if __name__ == '__main__':
download_new_files()
ポイント
1000件を超えた場合を考慮してs3.list_objects_v2を使って再帰的にobject一覧を取得しています
boto2版
# -*- coding: utf-8 -*-
import os
import boto
import pytz
from dateutil.parser import parse
from datetime import datetime, timedelta
from boto.s3.bucket import Bucket
s3_bucket_name = os.getenv('AWS_S3_BUCKET_NAME')
s3_conn = boto.connect_s3(aws_access_key_id=os.getenv('AWS_S3_ACCESS_KEY_ID'), aws_secret_access_key=os.getenv('AWS_S3_SECRET_ACCESS_KEY'))
boto2_bucket = Bucket(connection=s3_conn, name=s3_bucket_name)
def download_new_files(minutes=120):
utc_now = datetime.now(pytz.timezone('utc')) - timedelta(minutes=minutes)
prefix = 'baseball/'
res = boto2_bucket.list(prefix=prefix)
# 日付降順にsort
res_sorted = sorted(res, key=lambda x: x.last_modified, reverse=True)
download_path = '/var/tmp/'
if not os.path.isdir(download_path + prefix):
os.mkdir(download_path + prefix)
for key_object in res_sorted:
last_modified = parse(key_object.last_modified)
if last_modified < utc_now:
break
key_object.get_contents_to_filename(download_path + key_object.key)
print(key_object.key + ' download complete.')
if __name__ == '__main__':
download_new_files()
ポイント
boto.s3.bucket.list()関数でboto.s3.bucketlistresultset.BucketListResultSetが返ってくる。中身はboto.s3.key。
keyオブジェクトにはboto3の取得結果と同様に最終更新日(last_modified)が含まれるが、datetime型ではなくて文字列なので、dateutil.parser.parseで変換している。
詳しい方に教えてもらいたいこと
- boto2のboto.s3.bucket.list()に件数の上限があるのかどうか。boto3版のlist_handler()みたいな考慮は必要?
- 自前でsortせずにS3から直近の更新ファイルを取得する方法
参考
Boto 3 Documentation 1.9.222
boto v2.49.0 API Reference
PythonでYYYY-MM-DDTHH:mm:ss.000Z時刻形式をMM/DD/YYYY時刻形式に変換するにはどうすればよいですか?