S3のオブジェクトの存在確認をする方法【Python boto3】

概要

PythonでS3のオブジェクトが存在するかどうかを確認する方法を説明します。 boto3にはresourceclientの2つのAPIがあり、それぞれの方法を紹介します。

実際にLINE Botの開発で、ユーザーごとの設定ファイルがS3に存在するかチェックする必要があり、この方法を使いました。

resource vs client どちらを使うべきか

boto3には2つのAPIレベルがあります。

API特徴適したユースケース
resource高レベルAPI、オブジェクト指向シンプルな操作、可読性重視
client低レベルAPI、AWS APIに近い細かい制御、パフォーマンス重視

結論: 単純な存在確認ならclienthead_objectがおすすめです。理由は以下の通りです。

  • head_objectはオブジェクトのメタデータのみを取得するため軽量
  • resourceload()も内部的にはhead_objectを呼んでいる
  • clientの方がAWS APIに近く、挙動が明確

boto3.clientを利用する方法(推奨)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import boto3
from botocore.exceptions import ClientError

def check_s3_object_exists(bucket_name: str, object_key: str) -> bool:
    """S3オブジェクトの存在確認"""
    s3 = boto3.client('s3')
    try:
        s3.head_object(Bucket=bucket_name, Key=object_key)
        return True
    except ClientError as e:
        error_code = e.response['Error']['Code']
        if error_code == '404':
            return False
        # 404以外のエラー(権限不足など)は再raise
        raise

# 使用例
if check_s3_object_exists('my-bucket', 'path/to/file.json'):
    print("オブジェクトが存在します")
else:
    print("オブジェクトが存在しません")

ポイント

  • head_objectはオブジェクトの内容をダウンロードせず、メタデータのみを取得
  • 404エラー以外(403: アクセス拒否など)は別のエラーなので再raiseする
  • 関数化しておくとテストしやすい

boto3.resourceを利用する方法

オブジェクト指向的に書きたい場合はこちらも使えます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import boto3
from botocore.exceptions import ClientError

def check_s3_object_exists_resource(bucket_name: str, object_key: str) -> bool:
    """S3オブジェクトの存在確認(resource版)"""
    s3 = boto3.resource('s3')
    try:
        s3.Object(bucket_name, object_key).load()
        return True
    except ClientError as e:
        error_code = e.response['Error']['Code']
        if error_code == '404':
            return False
        raise

よくあるハマりポイント

1. 権限不足を404と間違える

S3バケットへのアクセス権限がない場合、403エラーが返ります。 404だけをキャッチして「存在しない」と判断すると、権限の問題を見逃します。

1
2
3
4
5
6
7
8
9
# NG: 404以外のエラーを握りつぶしている
except ClientError:
    return False  # 権限エラーも「存在しない」扱いになる

# OK: 404以外は再raise
except ClientError as e:
    if e.response['Error']['Code'] == '404':
        return False
    raise  # 権限エラーなどは呼び出し元で処理

2. list_objectsを使う方法は非効率

list_objectsでプレフィックス検索する方法もありますが、オブジェクト数が多いと遅くなります。 単一オブジェクトの存在確認にはhead_objectを使いましょう。

まとめ

  • S3オブジェクトの存在確認にはhead_objectを使う
  • 404エラー以外は権限不足などの可能性があるので適切に処理する
  • resourceclientどちらでも可能だが、clientの方がシンプル

参考

関連記事