Boto3, python and how to handle errors

I just picked up python as my go-to scripting language and I am trying to figure how to do proper error handling with boto3.

I am trying to create an IAM user:

    def create_user(username, iam_conn):
        try:
            user = iam_conn.create_user(UserName=username)
            return user
        except Exception as e:
            return e

When the call to create_user succeeds, i get a neat object that contains the http status code of the API call and the data of the newly created user.

Example:

    {'ResponseMetadata': 
          {'HTTPStatusCode': 200, 
           'RequestId': 'omitted'
          },
     u'User': {u'Arn': 'arn:aws:iam::omitted:user/omitted',
               u'CreateDate': datetime.datetime(2015, 10, 11, 17, 13, 5, 882000, tzinfo=tzutc()),
               u'Path': '/',
               u'UserId': 'omitted',
               u'UserName': 'omitted'
              }
    }

This works great. But when this fails (like if the user already exists), i just get an object of type botocore.exceptions.ClientError with only text to tell me what went wrong.

Example: ClientError('An error occurred (EntityAlreadyExists) when calling the CreateUser operation: User with name omitted already exists.',)

This (AFAIK) makes error handling very hard because i can't just switch on the resulting http status code (409 for user already exists according to the AWS API docs for IAM). This makes me think that i must be doing something the wrong way. The optimal way would be for boto3 to never throw exceptions, but juts always return an object that reflects how the API call went.

Can anyone enlighten me on this issue or point me in the right direction?

Thanks a lot!

Use the response contained within the exception. Here is an example:

    import boto3
    from botocore.exceptions import ClientError

    try:
        iam = boto3.client('iam')
        user = iam.create_user(UserName='fred')
        print "Created user: %s" % user
    except ClientError as e:
        if e.response['Error']['Code'] == 'EntityAlreadyExists':
            print "User already exists"
        else:
            print "Unexpected error: %s" % e

The response dict in the exception will contain the following:

  • ['Error']['Code'] e.g. 'EntityAlreadyExists' or 'ValidationError'
  • ['ResponseMetadata']['HTTPStatusCode'] e.g. 400
  • ['ResponseMetadata']['RequestId'] e.g. 'd2b06652-88d7-11e5-99d0-812348583a35'
  • ['Error']['Message'] e.g. "An error occurred (EntityAlreadyExists) ..."
  • ['Error']['Type'] e.g. 'Sender'

For more information see botocore error handling.

[Updated: 2018-03-07]

The AWS Python SDK has begun to expose service exceptions on clients (though not on resources) that you can explicitly catch, so it is now possible to write that code something like this:

    import boto3
    from botocore.exceptions import ClientError, ParamValidationError

    try:
        iam = boto3.client('iam')
        user = iam.create_user(UserName='fred')
        print "Created user: %s" % user
    except iam.exceptions.EntityAlreadyExistsException:
        print "User already exists"
    except ParamValidationError as e:
        print "Parameter validation error: %s" % e
    except ClientError as e:
        print "Unexpected error: %s" % e

Unfortunately, there is currently no documentation for these exceptions.

From: stackoverflow.com/q/33068055

Back to homepage or read more recommendations: