0
votes

We have a Cosmos DB from which we are trying to retrieve data using different parameters using a http triggered function API. I'm aware of the cosmos input binding but for this I need to put in my SQL query in the function.json file and this is fine if all the parameters are present in the query. The problem is, I would like to fetch data based on different parameters and it is possible that not all these parameters will be sent for each query. Is there a way this function API dynamic enough to create the SQL query in run time and fetch the data from Cosmos?

Instead of using the input binding, I tried using the Cosmos python SDK but was getting the below error. "Exception: AttributeError: module 'azure.functions' has no attribute 'In'".

When I normally run a python program to access cosmos outside functions, it is working fine which tells me that I have the necessary libraries already imported. But this is failing when calling from python functions. I've already checked that I'm pointing to the correct interpreter (python 3.8).

Is there something I'm missing? Below is my code

import logging
from azure.cosmos import exceptions, CosmosClient, PartitionKey
import azure.functions as func


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

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        endpoint = "https://xxxx.documents.azure.com:443/"
        key = '******=='
        client = CosmosClient(endpoint, key)
        database_name = 'mydb'
        database = client.create_database_if_not_exists(id=database_name)
        container_name= 'mycoll'
        container = database.create_container_if_not_exists(id=container_name,partition_key=PartitionKey(path="/name"),
            offer_throughput=400)

        query = 'SELECT * FROM c WHERE c.name = "Anupam"'
        items = list(container.query_items(query=query, enable_cross_partition_query=True))
        print(items)
        return func.HttpResponse(items, status_code=200)
    else:
        return func.HttpResponse(
             "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",
             status_code=200
        )

I introduced the below in the requirements.txt. azure-functions azure.cosmos

{[2021-02-10T06:34:16.248Z] Worker failed to function id 4af477f8-eff0-4937-b87f-98f7828d95ec.
[2021-02-10T06:34:16.250Z] Result: Failure
Exception: AttributeError: module 'azure.functions' has no attribute 'In'
Stack:   File "C:\Program Files\Microsoft\Azure Functions Core Tools\workers\python\3.8/WINDOWS/X64\azure_functions_worker\dispatcher.py", line 271, in _handle__function_load_request
    func = loader.load_function(
  File "C:\Program Files\Microsoft\Azure Functions Core Tools\workers\python\3.8/WINDOWS/X64\azure_functions_worker\utils\wrappers.py", line 32, in call
    return func(*args, **kwargs)
  File "C:\Program Files\Microsoft\Azure Functions Core Tools\workers\python\3.8/WINDOWS/X64\azure_functions_worker\loader.py", line 76, in load_function
    mod = importlib.import_module(fullmodname)
  File "C:\Users\dell\AppData\Local\Programs\Python\Python38\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 961, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "D:\Visual Studio\Projects\Functions1\SBTopicTrigger1\__init__.py", line 5, in <module>
    def main(message: func.ServiceBusMessage, inputdocument: func.In[func.Document], outputSbMsg:func.ServiceBusMessage):
.}

Below is my function.json

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ]
}

Any ideas how to get rid of this "Exception: AttributeError: module 'azure.functions' has no attribute 'In'" Error?

1
Why your python code include '{}'? Is this the problem coming from? - Cindy Pau
Sorry, that was a typo. Have removed the extra curly braces. - Anupam Chand
Do you use 'In' in somewhere?:) - Cindy Pau
It seems there is no problem with your code, The error shows you didn't even start the function worker runtime. Could you try again? - Cindy Pau
I hope your database name and key were not the real thing?! I just removed them, but if they were, go a change your key NOW! - silent

1 Answers

0
votes

RTM

  • You have Cosmos input binding missing from function.json E.g.
    {
      "type": "cosmosDB",
      "name": "todoitems",
      "databaseName": "ToDoItems",
      "collectionName": "Items",
      "connectionStringSetting": "CosmosDBConnection",
      "direction": "in",
      "Id": "{Query.id}",
      "PartitionKey": "{Query.partitionKeyValue}"
    }
  • Python code input param type is wrong. Should be func.DocumentList not func.In
import logging
import azure.functions as func

def main(req: func.HttpRequest, todoitems: func.DocumentList) -> str:
    if not todoitems:
        logging.warning("ToDo item not found")
    else:
        logging.info("Found ToDo item, Description=%s", todoitems[0]['description'])

    return 'OK'