LoginSignup
0
1

More than 3 years have passed since last update.

boto3とboto2.49.0でS3からファイルを取得する方法

Posted at

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時刻形式に変換するにはどうすればよいですか?

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1