Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

An exception occurred : 's3.ServiceResource' object has no attribute 'head_object'

I am checking if an object exist in S3 bucket. Following is the code snippet that I am using. obj is the filename.

    s3 = boto3.resource('s3')
    try:
        s3.head_object(Bucket=bucket_name, Key=obj)
    except ClientError as e:
        return False

But it is throwing me exception :

An exception occurred in python_code : 's3.ServiceResource' object has no attribute 'head_object'

Reference I used for this API - https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.head_object

Could anyone help me fix this?

like image 689
gkr2d2 Avatar asked Dec 12 '19 09:12

gkr2d2


3 Answers

Try:

s3 = boto3.client('s3')

instead of

boto3.resource('s3')

like image 159
Ntwobike Avatar answered Nov 16 '22 20:11

Ntwobike


I am bundeling a detailed response here:

1. boto3.client("s3") will allow you to perform Low level API calls
2. boto3.resource('s3') will allow you to perform High level API calls

Read here: Difference in boto3 between resource, client, and session?

Your requirement/operation requires an action on a bucket rather on a object/resource in the bucket. So here, it make sense and that is how AWS people have differentiated here API calls wrapper in the above mentined client methods

That is the reason why here boto3.client("s3") comes in picture.

like image 18
Varun Singh Avatar answered Nov 16 '22 21:11

Varun Singh


The boto3 resource and client APIs are different. Since you instantiated a boto3.resource("s3") object, you must use methods available to that object. head_object() is not available to the resource but is available to the client. The other answers provided detail how if you switch to using the client API, you can then use the head_object() method. If you are using the resource API in the rest of the codebase, please note you can check whether items exist in a Bucket, it is just done a little differently. The example given in the Boto3 docs is:

import boto3

s3 = boto3.resource('s3')
bucket = s3.Bucket('my-bucket')
for obj in bucket.objects.all():
    print(obj.key)  # Change this to check membership, etc.

Why use resource()? You do not have to make a second API call to get the objects! They're available to you as a collection on the bucket (via buckets.objects).

like image 5
Nathan Avatar answered Nov 16 '22 19:11

Nathan