在 Python 上使用 Azure 函数的雪花外部函数不起作用

Posted

技术标签:

【中文标题】在 Python 上使用 Azure 函数的雪花外部函数不起作用【英文标题】:Snowflake External Functions using Azure Functions on Python not working 【发布时间】:2021-05-26 08:12:21 【问题描述】:

我想创建一个可用于将行更新插入 MongoDB 的外部函数。我已经创建了这个函数,在本地使用 Postman 和发布后对其进行了测试。我遵循了https://docs.snowflake.com/en/sql-reference/external-functions-creating-azure-ui.html 的文档,起初,我使用了他们建议的 javascript 函数来测试和工作。但是,当我运行它 python 时,我得到一个错误。这是代码。

import logging

import azure.functions as func
import pymongo
import json
import os
from datetime import datetime

cluster = pymongo.MongoClient(os.environ['MongoDBConnString'])
db = cluster[f"os.environ['MongoDB']"]
collection = db[f"os.environ['MongoDBCollection']"]

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:
        return func.HttpResponse(f"Hello, name. This HTTP triggered function executed successfully.")
    else:
        collection.update_one(
                filter=
                    '_id':req_body['_id']
                ,
                update=
                    '$set': 'segment_ids': req_body['segment_ids']
                ,
                upsert=True)
        return func.HttpResponse(
                json.dumps("status_code": 200,
                "status_message": "Upsert Success",
                "Timestamp": datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S"),
                "_id": req_body['_id']),
                status_code=200,
                mimetype="text/plain"
        )

错误指出req_body 在定义之前被引用,在'_id':req_body['_id'] 行失败。在 Snowflake 中,我创建了一个名为 mongoUpsert(body variant) 的外部函数,我正在解析一个简单的查询以进行测试。

select mongoUpsert(object_construct('_id', 'someuuid', 'segment_ids;, array_construct(1,2,3,4)))

据我所知,由于某种原因,该函数没有收到我在 Snowflake 中解析的body。我不知道我做错了什么。谁能帮我?谁能解释一下 Snowflake 是如何发送参数(如正文、参数、标题)的,有没有办法指定我是否要解析正文或参数?

【问题讨论】:

【参考方案1】:

外部函数以特定格式发送和接收数据。所有参数都在请求正文中发送。

https://docs.snowflake.com/en/sql-reference/external-functions-data-format.html

您可以结帐snowflake-labs 用于外部函数示例。

有一个专门为Azure Python functions 调用 Translator API。

【讨论】:

【参考方案2】:

我从头开始,在 Snowflake 中一层一层剥离。因此,Snowflake 参数被解析为函数体,但包裹在一个数组中,然后该数组被包裹在另一个名为 'data' 的对象中。此外,它期望与响应返回相同的模式。下面是使用 Python 时用于 Azure Functions 的模板。

import logging
import azure.functions as func
import json

def main(req: func.HttpRequest) -> func.HttpResponse:
    # Get body response from Snowflake
    req_body = req.get_json()['data'][0][1]

    ###### Do Something
    
    # Return Response
    message = "Task": "Completed"
    return func.HttpResponse(
        json.dumps('data': [[0, message]]),
        status_code=200)

例如,我使用了一个简单的 JSON 对象:


  "_id": "someuuid"

并在 Snowflake 中创建了一个名为 testfunc(body variant) 的外部函数,并使用 select testfunc(object_construct('_id', 'someuuid')) 调用它。 如果您要记录响应(使用logging.info(req.get_json())),它将打印以下内容


  "data": 
  [
    [
      0,
      
        "_id": "someuuid"
      
    ]
  ]

所以为了得到我在雪花中输入的干净输入,我有这条线

req_body = req.get_json()['data'][0][1]

但是,在我尝试回显输入并注意到它在没有包装的情况下返回它之前,我一直在响应中收到错误。返回的正文需要是一个字符串(因此为什么使用json.dumps()),但它也需要包装。所以要打印出来,首先定义一个你想要的消息(可能是输入的计算或确认),然后将消息包装在'data': [[0, message]]中,最后编译为字符串(json.dumps()

【讨论】:

以上是关于在 Python 上使用 Azure 函数的雪花外部函数不起作用的主要内容,如果未能解决你的问题,请参考以下文章

使用 Azure 数据工厂将数据加载到雪花时出现问题

如何在 Azure 数据工厂中为雪花连接执行下推优化

我们如何使用 Azure AD 使用 DB Visualizer 连接到雪花

如何将 Azure MLStudio 与 Snowflake 连接

雪花 - Azure 文件上传 - 如果文件大小超过 40MB,我如何对文件进行分区

如何为 Http 触发的 Azure 函数(隔离/进程外)生成 Api 客户端?