1
votes

I want to upload JSON data as a .json file to Azure storage blobs using Azure Functions in Python.

Because I am using Azure Functions and not an actual server, I do not want to (and probably cannot) create a temporary file in local memory and upload that file to Azure blob storage using the Azure Blob storage client library v2.1 for Python (reference link here). Therefore, I want to use output blob storage bindings for Azure Functions (reference link here).

I am testing this out in an Azure Functions with an HTTP Trigger. I take in an Azure blob through an input blob storage binding (which is working just fine), process it, and update it by uploading a new Azure blob that overrides it (which is what I need help with). My function.json file looks like this:

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "name": "inputblob",
      "type": "blob",
      "path": "{containerName}/{blobName}.json",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "in"
    },
    {
      "name": "outputblob",
      "type": "blob",
      "path": "{containerName}/{blobName}.json",
      "connection": "MyStorageConnectionAppSetting",
      "direction": "out"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ]
}

And my Python code looks like this:

import logging
import azure.functions as func
import azure.storage.blob
from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient
import json, os

def main(req: func.HttpRequest, inputblob: func.InputStream, outputblob: func.Out[func.InputStream]) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    # Initialize variable for tracking any changes
    anyChanges= False

    # Read JSON file
    jsonData= json.loads(inputblob.read())

    # Make changes to jsonData (omitted for simplicity) and update anyChanges

    # Upload new JSON file
    if anyChanges:
        outputblob.set(jsonData)

    return func.HttpResponse(f"Input data: {jsonData}. Any changes: {anyChanges}.")

However, this isn't working at all, with the following error being thrown (screenshot):

Value 'func.Out' is unsubscriptable

What am I missing?

1

1 Answers

1
votes

You want bytes or str, not InputStream, like this:

def main(inputblob: func.InputStream, outputblob: func.Out[bytes], context: func.Context):
    ...
    # Write to output blob
    outputblob.set(jsonData)

InputStream represents an input blob.

See this sample for str and this one for bytes.

Later update:

The call to json.loads() returns a dictionary and for some reason outputblob.set() freaks out and needs some handholding, like this:

def main(req: func.HttpRequest,
         inputblob: func.InputStream,
         outputblob: func.Out[bytes]) -> func.HttpResponse:

    jsonData = json.loads(inputblob.read())
    outputblob.set(str(jsonData))

    return func.HttpResponse(f"Input JSON: {jsonData}")

That should work (well it works on func version 2.7.1948 at least).