title: How to handle errors with boto3?
body: <p>I am trying to figure how to do proper error handling with boto3.</p>
  
  <p>I am trying to create an IAM user:</p>
  
  <pre><code>def create_user(username, iam_conn):
      try:
          user = iam_conn.create_user(UserName=username)
          return user
      except Exception as e:
          return e
  </code></pre>
  
  <p>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.</p>
  
  <p>Example:</p>
  
  <pre><code>{'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'
            }
  }
  </code></pre>
  
  <p>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.</p>
  
  <p>Example:
  ClientError('An error occurred (EntityAlreadyExists) when calling the CreateUser operation: User with name omitted already exists.',)</p>
  
  <p>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.</p>
  
  <p>Can anyone enlighten me on this issue or point me in the right direction?</p>