Difference in boto3 between resource, client, and session?
Client and Resource are two different abstractions within the boto3 SDK for making AWS service requests. You would typically choose to use either the Client abstraction or the Resource abstraction. I've outlined the differences between Client and Resource below to help readers decide which to use.
Session is largely orthogonal to the concepts of Client and Resource (but is used by both).
- this is the original boto3 API abstraction
- provides low-level AWS service access
- all AWS service operations are supported by clients
- exposes botocore client to the developer
- typically maps 1:1 with the AWS service API
- snake-cased method names (e.g. ListBuckets API => list_buckets method)
- generated from AWS service description
Here's an example of client-level access to an S3 bucket's objects:
import boto3client = boto3.client('s3')response = client.list_objects_v2(Bucket='mybucket')for content in response['Contents']: obj_dict = client.get_object(Bucket='mybucket', Key=content['Key']) print(content['Key'], obj_dict['LastModified'])
Note: this client-level code is limited to listing at most 1000 objects. You would have to use a paginator, or implement your own loop, calling list_objects_v2() repeatedly with a continuation marker if there were more than 1000 objects.
- this is the newer boto3 API abstraction
- provides high-level, object-oriented API
- does not provide 100% API coverage of AWS services
- uses identifiers and attributes
- has actions (operations on resources)
- exposes subresources and collections of AWS resources
- generated from resource description
Here's the equivalent example using resource-level access to an S3 bucket's objects (all):
import boto3s3 = boto3.resource('s3')bucket = s3.Bucket('mybucket')for obj in bucket.objects.all(): print(obj.key, obj.last_modified)
Note: in this case 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. These collections of subresources are lazily-loaded.
You can see that the
Resource version of the code is much simpler, more compact, and has more capability (it does pagination for you). The
Client version of the code would actually be more complicated than shown above if you wanted to include pagination.
- stores configuration information (primarily credentials and selected region)
- allows you to create service clients and resources
- boto3 creates a default session for you when needed
A useful resource to learn more about these boto3 concepts is the introductory re:Invent video.
I'll try and explain it as simple as possible. So there is no guarantee of the accuracy of the actual terms.
Session is where to initiate the connectivity to AWS services. E.g. following is default session that uses the default credential profile(e.g. ~/.aws/credentials, or assume your EC2 using IAM instance profile )
sqs = boto3.client('sqs')s3 = boto3.resource('s3')
Because default session is limit to the profile or instance profile used, sometimes you need to use the custom session to override the default session configuration (e.g. region_name, endpoint_url, etc. ) e.g.
# custom resource session must use boto3.Session to do the overridemy_west_session = boto3.Session(region_name = 'us-west-2')my_east_session = boto3.Session(region_name = 'us-east-1')backup_s3 = my_west_session.resource('s3')video_s3 = my_east_session.resource('s3')# you have two choices of create custom client session. backup_s3c = my_west_session.client('s3')video_s3c = boto3.client("s3", region_name = 'us-east-1')
Resource : This is the high-level service class recommended to be used. This allows you to tied particular AWS resources and passes it along, so you just use this abstraction than worry which target services are pointed to. As you notice from the session part, if you have a custom session, you just pass this abstract object than worrying about all custom regions,etc to pass along. Following is a complicated exampleE.g.
import boto3 my_west_session = boto3.Session(region_name = 'us-west-2')my_east_session = boto3.Session(region_name = 'us-east-1')backup_s3 = my_west_session.resource("s3")video_s3 = my_east_session.resource("s3")backup_bucket = backup_s3.Bucket('backupbucket') video_bucket = video_s3.Bucket('videobucket')# just pass the instantiated bucket objectdef list_bucket_contents(bucket): for object in bucket.objects.all(): print(object.key)list_bucket_contents(backup_bucket)list_bucket_contents(video_bucket)
Client is a low level class object. For each client call, you need to explicitly specify the targeting resources, the designated service target name must be pass long. You will lose the abstraction ability.
For example, if you only deal with the default session, this looks similar to boto3.resource.
import boto3 s3 = boto3.client('s3')def list_bucket_contents(bucket_name): for object in s3.list_objects_v2(Bucket=bucket_name) : print(object.key)list_bucket_contents('Mybucket')
However, if you want to list objects from a bucket in different regions, you need to specify the explicit bucket parameter required for the client.
import boto3 backup_s3 = my_west_session.client('s3',region_name = 'us-west-2')video_s3 = my_east_session.client('s3',region_name = 'us-east-1')# you must pass boto3.Session.client and the bucket name def list_bucket_contents(s3session, bucket_name): response = s3session.list_objects_v2(Bucket=bucket_name) if 'Contents' in response: for obj in response['Contents']: print(obj['key'])list_bucket_contents(backup_s3, 'backupbucket')list_bucket_contents(video_s3 , 'videobucket')