Home > Blockchain >  Best way to raise an exception and simultaneously return a HTTP error code in a Python Cloud Functio
Best way to raise an exception and simultaneously return a HTTP error code in a Python Cloud Functio

Time:03-01

I am having some trouble combining two requirements that were communicated to me.

The initial requirement I had was to handle exceptions in the GCP Cloud Function I had created to insert JSON data into BigQuery. The basic logic was as follows:

import json
import google.auth
from google.cloud import bigquery

class SomeRandomException(Exception):
    """Text explaining the purpose of this exception"""

def main(request):
    """Triggered by another HTTP request"""

    # Instantiation of BQ client
    credentials, your_project_id = google.auth.default(
        scopes=["https://www.googleapis.com/auth/cloud-platform"]
    )
    client = bigquery.Client(credentials=credentials, project=your_project_id, )

    # JSON reading
    json_data: dict = request.get_json()

    final_message: str = ""
    table_name = "someTableName"

    for row in json_data:
        rows_to_insert: list = []                    
        rows_to_insert.append(row["data"])

        if rows_to_insert:
            errors: list = client.insert_rows_json(
                table_name, rows_to_insert, row_ids=[None] * len(rows_to_insert)
            )
            if errors == []:
                final_message = f"\n{len(rows_to_insert)} row(s) successfully inserted in table\n"
            else:
                raise SomeRandomException(
                    f"Encountered errors while inserting rows into table: {errors}"
                )

    return final_message

(please note that there are other exceptions being handled in the code but I tried to simplify the above logic to make things easier to analyze)

Then I received a second requirement saying that, in addition to raising an exception, I had to return a HTTP error code. I discovered in another StackOverflow question that it was easy to return an error code along with some message. But I haven't found anything that clearly explains how to return that error code and, at the same time, raise an exception. From what I know, raise and return are mutually exclusive statements. So, is there any solution to gracefully combine the exception handling and the HTTP error?

Would the below snippet for instance be acceptable or is there a better way? I'm really confused because an exception is supposed to use a raise whereas a HTTP code needs a return.

else:
    return SomeRandomException(
        f"Encountered errors while inserting rows into table: {errors}"
    ), 500

CodePudding user response:

Building on John's comment. You want to raise the exception in the code you have and then add a try-except to catch/handle the exception and return the error.

class SomeRandomException(Exception):
    # add custom attributes if need be
    pass


try: 
    # your code ...
    else:
        raise SomeRandomException("Custom Error Message!")
except SomeRandomException as err:
    # caught exception, time to return error
    response = {
        "error": err.__class__.__name__,
        "message": "Random Exception occured!"
    }
    # if exception has custom error message
    if len(err.args) > 0:
        response["message"] = err.args[0]
    return response, 500

To go one step further you could also integrate Cloud Logging with the Python root logger so that right before returning the error you also log the error to Cloud Function's logs like so: logging.error(err)

This would just help make the logs easier to query later on.

  • Related