LoginSignup
16
17

More than 5 years have passed since last update.

Boto 3 で、指定した key が指定した bucket の中にあるかを確かめるには

Last updated at Posted at 2015-07-02

Boto 3 では、Boto 2 の頃まであった key の存在をたしかめる exists() にあたるメソッドが無くなっています。ですが、以下のように list_objects() を使うことで同様の機能を実現できます。

exists.py
from boto3 import Session
s3client = Session().client('s3')

def exists(bucket: str, key: str) -> bool:
    """
    指定した key が指定した bucket の中に存在するか

    :param bucket: (str) bucket name
    :param key: (str) key
    :return: (bool)
    """
    contents = s3client.list_objects(Prefix=key, Bucket=bucket).get("Contents")
    if contents:
        for content in contents:
            if content.get("Key") == key:
                return True
    return False

解説

list_objects() は以下のような形のハッシュを返します。

{
    'IsTruncated': True|False,  # 結果が寸断されたか。されていれば True
    'Marker': 'string',
    'NextMarker': 'string',
    'Contents': [
        {
            'Key': 'string',
            'LastModified': datetime(2015, 1, 1),
            'ETag': 'string',
            'Size': 123,
            'StorageClass': 'STANDARD'|'REDUCED_REDUNDANCY'|'GLACIER',
            'Owner': {
                'DisplayName': 'string',
                'ID': 'string'
            }
        },
    ],
    'Name': 'string',
    'Prefix': 'string',
    
}

'Contents' がキモで、ここに該当する key の配列が入ります。該当する key がないと 'Contents' は返り値に含まれません。したがって、'Contents' が含まれるかを調べて、そのリスト内の辞書の 'Key' の値と、引数で与えた key が一致するものがあれば exists() にあたる機能を再現できます。

Prefix に key のフルパス? を指定するのは若干違和感を覚えますが、Prefix とはそういうものだと理解しました。

2017/06/29 追記

以下のケースで正しく動作しないことがあったので、修正しました (thx, @masahiro_toriumi さん)

Prefixはあくまでもキーの接頭辞を指定するものなので、例えば、"MyBucket/aaa.txt"というPrefixでlist_objectをコールした場合、"MyBucket/aaa.txt.bak"などにも引っかかるため、"MyBucket/aaa.txt"というキーが存在するかどうかは正確には判断できない

16
17
3

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
16
17