156

I'm trying to write "good" python and capture a S3 no such key error with this:

session = botocore.session.get_session()
client = session.create_client('s3')
try:
    client.get_object(Bucket=BUCKET, Key=FILE)
except NoSuchKey as e:
    print >> sys.stderr, "no such key in bucket"

But NoSuchKey isn't defined and I can't trace it to the import I need to have it defined.

e.__class__ is botocore.errorfactory.NoSuchKey but from botocore.errorfactory import NoSuchKey gives an error and from botocore.errorfactory import * doesn't work either and I don't want to capture a generic error.

theist
  • 2,840
  • 2
  • 23
  • 22
  • For exceptions like `botocore.errorfactory.NoSuchKey`, modeled exceptions needs to be accessed through the client object. So rather than having `botocore.errorfactory.NoSuchKey` you need `client.exceptions.NoSuchKey` – simpleuser Feb 27 '21 at 00:59

4 Answers4

184
from botocore.exceptions import ClientError

try:
    response = self.client.get_object(Bucket=bucket, Key=key)
    return json.loads(response["Body"].read())
except ClientError as ex:
    if ex.response['Error']['Code'] == 'NoSuchKey':
        logger.info('No object found - returning empty')
        return dict()
    else:
        raise
Mark Amery
  • 127,031
  • 74
  • 384
  • 431
Jose Alban
  • 6,533
  • 2
  • 31
  • 17
87

Using botocore 1.5, it looks like the client handle exposes the exception classes:

session = botocore.session.get_session()
client = session.create_client('s3')
try:
    client.get_object(Bucket=BUCKET, Key=FILE)
except client.exceptions.NoSuchKey as e:
    print >> sys.stderr, "no such key in bucket"
groner
  • 1,946
  • 15
  • 7
  • I'm opting for this one, as it's newer and also less generic. You can find some comments on GitHub regarding this method: https://github.com/boto/boto3/issues/1262#issuecomment-329314670 – Sylwester Kardziejonek May 03 '18 at 17:03
  • 6
    If you forgot to scroll like me: If you're using the high-level resource (`s3 = boto3.resource("s3")`), you can access the client and thus the Exception via `s3.meta.client.exceptions.NoSuchKey`. See https://stackoverflow.com/questions/38581465/boto3-get-a-resource-from-a-client – lorey Jul 02 '20 at 16:34
49

In boto3, I was able to access the exception in resource's meta client.

import boto3

s3 = boto3.resource('s3')
s3_object = s3.Object(bucket_name, key)

try:
    content = s3_object.get()['Body'].read().decode('utf-8')
except s3.meta.client.exceptions.NoSuchKey:
    print("no such key in bucket")
Randy
  • 1,298
  • 12
  • 8
38

I think the most elegant way to do this is in Boto3 is

session = botocore.session.get_session()
client = session.create_client('s3')

try:
    client.get_object(Bucket=BUCKET, Key=FILE)
except client.exceptions.NoSuchKey:
    print("no such key in bucket")

The documentation on error handling seems sparse, but the following prints the error codes this works for:

session = botocore.session.get_session()
client = session.create_client('s3')
try:
    try:
        client.get_object(Bucket=BUCKET, Key=FILE)
    except client.exceptions.InvalidBucketName:
        print("no such key in bucket")
except AttributeError as err:
    print(err)

< botocore.errorfactory.S3Exceptions object at 0x105e08c50 > object has no attribute 'InvalidBucketName'. Valid exceptions are: BucketAlreadyExists, BucketAlreadyOwnedByYou, NoSuchBucket, NoSuchKey, NoSuchUpload, ObjectAlreadyInActiveTierError, ObjectNotInActiveTierError

JeffSolo
  • 481
  • 4
  • 4