0

Background

I am writing an AWS Lambda function that uses the Boto3 SDK to access AWS services in Python.

Context

My main function/lambda handler makes an API request. I check the status code from the request and raise custom exceptions based on the response code. For each except I create a descriptive message to send an email via SNS to notify me about the error.

What I've tried

I read this thread on custom python exceptions with error codes and error messages

I read this thread on nested excpetions but did not really understand how to apply it to my situation.

I also read this thread on handling exceptions that occur within except clause but I do not understand how to translate it.

Question

How do I handle the SNS sending if that raises an error and return the proper information?

class Error(Exception):
    pass

class Error_401(Error):
    pass

class Error_403(Error):
    pass

class Error_404(Error):
    pass

class Error_500(Error):
    pass

# This syntax is most likely wrong, I just pasted it
# from link 1
class SNS_Send_Error(Error):
    def __init__(self, code):
        self.code = code
    def __str__(self):
        return repr(self.code)

def create_sns_client(arn,message):
    try:
        sns = boto3.client("sns")
        res = sns.publish(
            TargetArn=arn,
            Message=json.dumps({"default": json.dumps(message)}),
            MessageStructure="json"
        )
    except ClientError as e:
        code = e.reponse['ResponseMetadata']['HTTStatusCode']
        message = e.response['Error']['Code']
        print(message)
        raise SNS_Send_Error('SNS failed to send message. \
            Responed with error code: {}'.fomat(code),code)
    return res

def status_codes(arg):
    if arg == 401:
        raise Error_401
    elif arg == 403:
        raise Error_403
    elif arg == 404:
        raise Error_404
    elif arg == 500:
        raise Error_500

def lambda_handler(event, context):

    # Other Code ...

    # Request data from GH API
    try:
        res = request_gh_data(gh_secret, jobId)
        status = res.status_code
        gh_response = res.json()

        status_codes(status)

    except Error_401 as e:
        message = generate_error(gh_response['message'], context)
        create_sns_client(message)
        return {
            'statusCode': status,
            'body': message
        }
    except Error_403 as e:
        message = generate_error(gh_response['message'], context)
        create_sns_client(message)
        return {
            'statusCode': status,
            'body': message
        }
    except Error_404 as e:
        message = generate_error(gh_response['message'], context)
        create_sns_client(message)
        return {
            'statusCode': status,
            'body': message
        }
    except Error_500 as e:
        message = generate_error(gh_response['message'], context)
        create_sns_client(message)
        return {
            'statusCode': status,
            'body': message
        }
    except SNS_Send_Error as e:
        code = e.reponse['ResponseMetadata']['HTTStatusCode']
        message = e.response['Error']['Code']
        print(message)
        return {
            "statusCode": code,
            "body": message 
        }

    # Additional Code

    return {
        'statusCode': 200,
        'body': "Success!"
    }

We can see that in each except block, I send a message based on the type of error that occurs. How should I handle the message sending error in the most "Pythonic" manner.

Garrett
  • 319
  • 1
  • 13
  • 1
    Is `request_gh_data` using `requests` and returning a `requests.Response` object? You can use [`response.raise_for_status()`](https://docs.python-requests.org/en/latest/api/#requests.Response.raise_for_status) if that's the case instead of creating custom exceptions – Iain Shelvington Jun 25 '21 at 00:59
  • @IainShelvington this is great. Thanks for cleaning up that part of the code. How should I handle the nested exception? – Garrett Jun 25 '21 at 01:21
  • 1
    you should now have only a single `except` that catches `requests.HTTPError`? You can have a `try/except` nested here to catch `SNS_Send_Error` – Iain Shelvington Jun 25 '21 at 01:24
  • @IainShelvington alright, I needed confirmation that nesting was alright. Thanks! I can write up an answer for this thread tomorrow based on your advice and tag you. Or you can write it yourself ill accept it. – Garrett Jun 25 '21 at 04:45

1 Answers1

0

You can use except without specifying the exception type to handle any kind of Exception. Then you can get what was the cause of the exception with e.__class__.

try:
    # code to be executed
except Exception as e:
    # you can give your message 
    # or do the task you want
    # based on the exception class
    print('exception raised: ', e.__class__)
fizgi
  • 40
  • 8