【Lambda】list_objectsでひっかかったこと

# やりたいこと
* list_objectsで指定S3バケット上のキー一覧を取得
    * あるキーが存在するならファイルにデータを追記
    * あるキーが存在しない場合ファイルを新規作成
* ランタイムはPython3.9

# ①LambdaからS3バケットにアクセスできない
```Python:Error
[ERROR] ClientError: An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied
Traceback (most recent call last):
```
**解決策：LambdaにS3のアクセス権限を付与**
1.Lambda関数を管理しているIAMロールの概要ページにアクセス
![01_アクセス権限.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728375/cb40ccb5-e8e1-4144-0a47-b72e257f4c22.png)
2.「許可を追加」→「ポリシーをアタッチ」を選択
![02_アクセス権限.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728375/a28d0560-858f-b914-af67-92be3c9355c7.png)
3.追加したいポリシーを選んで「ポリシーをアタッチ」
※私はこのあと書き込み等も行いたかったため「AmazonS3FullAccess」を追加しましたが、読み込みだけなら「AmazonS3ReadOnlyAccess」で問題ありません。
![03_アクセス権限.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728375/7a8baf3a-4603-dc9b-124b-5d699692cc6f.png)
# ②キー名のみの取得ができない
**失敗例**
```Python:Example1
import boto3

s3_client = boto3.client("s3")
bucket = "testbucket"   #バケット名

response = s3_client.list_objects(Bucket=bucket)

print("##keylist")
print(response)
```
```Python:Result1
##keylist
{'ResponseMetadata': {'RequestId': '##########', 'HostId': '##########', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amz-id-2': '##########', 'x-amz-request-id': '##########', 'date': 'Fri, 12 Aug 2022 07:46:36 GMT', 'x-amz-bucket-region': 'ap-northeast-1', 'content-type': 'application/xml', 'transfer-encoding': 'chunked', 'server': 'AmazonS3'}, 'RetryAttempts': 0}, 'IsTruncated': False, 'Marker': '', 'Contents': [{'Key': 'apple.txt', 'LastModified': datetime.datetime(2022, 8, 12, 5, 19, 14, tzinfo=tzlocal()), 'ETag': '"##########"', 'Size': 0, 'StorageClass': 'STANDARD', 'Owner': {'DisplayName': '##########', 'ID': '##########'}}, {'Key': 'grape.txt', 'LastModified': datetime.datetime(2022, 8, 12, 5, 19, 14, tzinfo=tzlocal()), 'ETag': '"##########"', 'Size': 0, 'StorageClass': 'STANDARD', 'Owner': {'DisplayName': '##########', 'ID': '##########'}}, {'Key': 'peach.txt', 'LastModified': datetime.datetime(2022, 8, 12, 5, 19, 14, tzinfo=tzlocal()), 'ETag': '"##########"', 'Size': 0, 'StorageClass': 'STANDARD', 'Owner': {'DisplayName': '##########', 'ID': '##########'}}], 'Name': 'testbucket', 'Prefix': '', 'MaxKeys': 1000, 'EncodingType': 'url'}
```
キー名のみがリストで返されるものだと勘違いしていました。（一部伏字にしています）
**解決策**
```Python:Example2
import boto3

s3_client = boto3.client("s3")
bucket = "testbucket"   #バケット名

response = s3_client.list_objects(Bucket=bucket)
keys = []
for r in response.get("Contents")
    keys.append(r.get("Key"))

print("##keylist")
print(keys)
```
```Python:Result2
##keylist
['apple.txt', 'grape.txt', 'peach.txt']
```
# おまけ
指定S3バケットにあるキーが存在するかどうかで処理を分岐させる例文
```Python:Example3
import boto3

def lambda_handler(event, context):
    bucket = BUCKET   #バケット名
    key = KEY   #探したいキー名
    s3_client = boto3.client("s3")

    response = s3_client.list_objects(Bucket=bucket)
    keys = []
    for r in response.get("Contents")
        keys.append(r.get("Key"))

    if key in keys:
        #キーが存在する場合の処理
    else:
        #キーが存在しない場合の処理

    return {"statuscode":200}
```
# 参考
https://dev.classmethod.jp/articles/get-s3-object-with-python-in-lambda/

https://qiita.com/koji4104/items/15ac578e561f53a0dadc