I covered the basics of a Python Azure Function before; now I’m going to look at the bindings, function.json, as a way to get additional settings or storage. Most of the information can be found in the Python developer guide.
The guide recommends that the Azure functions are kept within there own folder (called
__app__ but you can change this) with tests and other files outside of this directory so they are not packaged up with the deployment. This is not the default if using the wizard in VS Code; if you move your code into a sub-directory afterwards you will need to re-initialise in VS Code in order to do local testing. Despite what the guide says, the
.gitignore file should remain in the root. If you are doing local testing you should also have Azure Storage Emulator running.
The majority of
function.json is taken up with the bindings array. The bindings link your function to other resources. All bindings will have the following three fields with additional fields determined by the type:
- name: Name of the binding; this should match the parameter name in your function entry point apart from
$return which binds to the returned output of the funtion. Note the name cannot contain underscores (unfortunately).
- type: As a minimum, there will be one binding with the trigger type used to call the function (HTTP, timer, queue etc.). Additional types can also be bound to the function like storage tables.
- direction: Either in (data is to be passed in to the function) or out (function will write data out to the binding).
Adding an additional binding to a storage table is a useful way to provide the function with configuration. Function apps are already attached to a storage account (connection string is stored in the AzureWebJobsStorage app setting); you can create a table in this storage account and put the configuration in there. Step 7 in the step-by-step guide above touched on storage account bindings – full details on binding a table can be found here.
When adding the binding in function.json, the partitionKey and rowKey are optional. If you do specify both this will point to a unique entity and the json string passed in with be an object with all the fields including partitionKey and rowKey. If you do not specify both then the json string passed in with be an array of objects that match the given partitionKey or rowKey. If you do not specify either the array will be the entire contents of the table.
Lets bind a table entity from the configuration table to our function by adding the following object to our bindings array:
We can then use load this configuration in our Azure function with the following code. Note the example is for a HTTP trigger function.
import azure.functions as func
def main(req: func.HttpRequest, config: str) -> func.HttpResponse:
configuration = json.loads(config)
That’s it; you now have a configuration dictionary with all the fields from the binded table entity. Also note that because the table is set in function.json, you can have different configuration entities for different functions. It’s a lot neater than having hundreds of app settings.
If using table(s) for configuration, this will necessitate creating them beforehand. You can use Azure Storage Explorer to do this; both to manage the tables in Azure and in the storage emulator when running locally.
Another common type to bind to is a queue (either a storage queue or a service bus queue). If used as a trigger you can use the function to respond to a message being placed into the queue. Binding to the function output allows you to write messages into a queue. Combining the two allows one function to call another; this is the Microsoft preferred method of doing this, rather the directly invoking the function with a HTTP request.
Binding a storage queue to the output is covered in step 7 of the tutorial. Creating a new function with an Azure Queue Storage trigger will create the necessary boilderplate code to use. There is not much more to it than that.
If you get the error message
Value 'func.Out' is unsubscriptable when adding the queue to the function parameters try uninstalling pylint with the following command
pip uninstall pylint – thanks to Stack Overflow as usual for this.
If you are looking for samples of other types of bindings check out the following repo.