2

Problem

I have an Azure Function HTTP triggered function written in Python 3.8. This function receives an incoming HTTP request and writes an entity to an Azure Table. If an incoming request tries to create a duplicate entry, Azure Table throws an EntityAlreadyExists error to the Azure Function runner. I would like to catch this exception and handle it accordingly.

Can I catch this exception in python using a try/except block from within the Azure Function? If so, how? If not, do you know why?

Things I have tried

  • try to run code, then except ValueError as err: to handle exception
  • try to run code, then except Exception as err: to handle exception
  • try to run code, then except EntityAlreadyExists as err: to handle exception

None of these were successful at catching the exception being thrown from Azure Table for a duplicate entry attempt.

Links

Error thrown

This is the error I am trying to catch from within my HTTP-triggered Azure Function

Executed 'Functions.myTable' (Failed, Id=xxx-xxx-xxx-xxx, Duration=1256ms)
System.Private.CoreLib: Exception while executing function: Functions.myTable. Microsoft.Azure.WebJobs.Host: Error while handling parameter _binder after function returned:. Microsoft.Azure.WebJobs.Extensions.Storage: The specified entity already exists.
RequestId:xxx-xxx-xxx-xxx
Time:2020-09-30T13:16:00.9339049Z (HTTP status code 409: EntityAlreadyExists. The specified entity already exists.
RequestId:xxx-xxx-xxx-xxx
Time:2020-09-30T13:16:00.9339049Z). Microsoft.WindowsAzure.Storage: The specified entity already exists.
RequestId:xxx-xxx-xxx-xxx
Time:2020-09-30T13:16:00.9339049Z.

--init--.py

Below is relevant portions of the py file for the Azure function. The question surrounds the try/except block in Lines 16-27 (line numbers not shown).

import logging
import json
import azure.functions as func

def main(req: func.HttpRequest, myTable: func.Out[str]) -> func.HttpResponse:

    body = req.get_json()

    data = { # Data to send to Azure Table
        "PartitionKey": body.get('var1'),
        "RowKey": body.get('var2'),
        "Property1" : body.get('var3'),
        "Property2" : body.get('var4')
    }

    try: # Try to send record to Azure Table

        myTable.set(json.dumps(data))

    except ValueError as err: # Respond with 409 if duplicate record

        logging.error(err)

        return func.HttpResponse(
            body=f'Record already exists.',
            status_code=409
        )

    else: # Otherwise, respond with 201 success

        return func.HttpResponse(
                body=f'Success.',
                status_code=201
            )

function.json

Below are the triggers and bindings json for the Azure function.

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "post"
      ]
    },
    {
      "name": "myTable",
      "type": "table",
      "tableName": "myTable",
      "connection": "AzureWebJobsStorage",
      "direction": "out"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ]
}
Bryan Winter
  • 45
  • 1
  • 1
  • 8
  • Can you update the question with relevant part of your azure function? – Abdul Niyas P M Sep 30 '20 at 13:45
  • @AbdulNiyasPM, great suggestion! I hope I didn't make the question too long. I added relevant portions of the py file and the bindings/triggers json. – Bryan Winter Sep 30 '20 at 15:06
  • What is `type(myTable)`? – Abdul Niyas P M Sep 30 '20 at 15:17
  • @AbdulNiyasPM, it is a class that Microsoft calls Out. It is defined in their azure.functions package. They have more documentation about Out class here: https://learn.microsoft.com/en-us/python/api/azure-functions/azure.functions.out?view=azure-python – Bryan Winter Sep 30 '20 at 17:21
  • More documentation on using Out class for creating an entity (record) in Azure Table: https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-table?tabs=python#output---usage – Bryan Winter Sep 30 '20 at 17:28
  • @BryanWinter It seems that the exception is thrown by Azure function sdk itself. We have no way to catch it. I suggest you implement insert action by yourself that you can catch exception. – Jim Xu Oct 01 '20 at 01:45

2 Answers2

0

If you are using python. Python can only use declarative binding mode, but not imperative binding mode, so if you want to use binding to achieve, it is impossible to use'try catch'.

The right way is put the logic in the content of the function and then you can use try catch.

Cindy Pau
  • 13,085
  • 1
  • 15
  • 27
0

Azure Table Storage has a new python library in preview release that is available for installation via pip. To install use the following pip command

pip install azure-data-tables

Within Azure Functions you can use a try/except block to catch exceptions thrown by a Tables response. The recommended way to access your Tables account from an Azure Functions is through an MSI enabled KeyVault client to retrieve your credential to authenticate your TableClient. An example function that tries to create a new table would look like:

import azure.functions as func

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    from azure.identity import ManagedIdentityCredential
    from azure.keyvault.secrets import SecretClient

    credential = ManagedIdentityCredential()
    client = SecretClient("https://tablesfunctions.vault.azure.net", credential)
    conn_str = client.get_secret("tables-connstr")

    from azure.data.tables import TableClient
    from azure.core.exceptions import ResourceExistsError

    table_client = TableClient.from_connection_string(conn_str, table_name="MyTableName")
    try:
        table_client.create_table()
    except ResourceExistsError:
        return func.HttpResponse("Table already exists")

(FYI I work on the Azure SDK for Python team.)

spkane31
  • 385
  • 2
  • 6