Partilhar via


Visão geral do modelo de programação de funções de dados do usuário do Fabric

O modelo de programação das funções de dados do utilizador do Fabric define os padrões e conceitos para criar funções no Fabric.

O fabric-user-data-functions SDK implementa este modelo de programação, fornecendo a funcionalidade necessária para criar e publicar funções executáveis. O SDK também permite que você se integre perfeitamente a outros itens no ecossistema do Fabric, como fontes de dados do Fabric. Esta biblioteca está disponível publicamente no PyPI e está pré-instalada nos itens de funções de dados do usuário.

Este artigo explica como usar o SDK para construir funções que podem ser invocadas a partir do portal Fabric, outros itens Fabric ou aplicações externas usando a API REST. Aprendes o modelo de programação e conceitos-chave com exemplos práticos.

Sugestão

Para detalhes completos sobre todas as classes, métodos e parâmetros, consulte a documentação de referência do SDK.

Começar com o SDK

Esta secção apresenta os componentes principais do SDK de Funções de Dados de Utilizador e explica como estruturar as suas funções. Aprende sobre as importações necessárias, decoradores e os tipos de dados de entrada e saída que as suas funções podem gerir.

SDK de funções de dados do usuário

O fabric-user-data-functions SDK fornece os componentes essenciais de que precisa para criar funções de dados de utilizador em Python.

Importações obrigatórias e inicialização

Cada ficheiro de funções de dados do utilizador deve importar o fabric.functions módulo e inicializar o contexto de execução:

import datetime
import fabric.functions as fn
import logging

udf = fn.UserDataFunctions()

O @udf.function() decorador

As funções marcadas com o @udf.function() decorador podem ser chamadas a partir do portal Fabric, de outro item Fabric ou de uma aplicação externa. As funções com este decorador devem especificar um tipo de retorno.

Exemplo:

@udf.function()
def hello_fabric(name: str) -> str:
    logging.info('Python UDF trigger function processed a request.')
    logging.info('Executing hello fabric function.')
    
    return f"Welcome to Fabric Functions, {name}, at {datetime.datetime.now()}!"

Funções auxiliares

Métodos em Python sem o @udf.function() decorador não podem ser invocados diretamente. Só podem ser chamadas a partir de funções decoradas e servem como funções auxiliares.

Exemplo:

def uppercase_name(name: str) -> str:
    return name.upper()

Tipos de entrada suportados

Você pode definir parâmetros de entrada para a função, como tipos de dados primitivos como str, int, float, etc. Os tipos de dados de entrada suportados são:

Tipo JSON Python Tipo de dados
String STR
Cadeia de caracteres de data e hora datetime
Booleano Bool
Números int, flutuar
Matriz lista[], exemplo lista[int]
Objeto dicionário
Objeto Pandas DataFrame
Objeto ou matriz de objetos Série Pandas

Observação

Para usar os tipos de DataFrame e Série do pandas, vá ao portal Fabric, encontre o seu espaço de trabalho e abra o item de funções de dados do utilizador. Selecione Gestão de Bibliotecas, procure o fabric-user-data-functions pacote e atualize-o para a versão 1.0.0 ou posterior.

Exemplo de corpo de solicitação para tipos de entrada suportados:

{
  "name": "Alice",                          // String (str)
  "signup_date": "2025-11-08T13:44:40Z",    // Datetime string (datetime)
  "is_active": true,                        // Boolean (bool)
  "age": 30,                                // Number (int)
  "height": 5.6,                            // Number (float)
  "favorite_numbers": [3, 7, 42],           // Array (list[int])
  "profile": {                              // Object (dict)
    "email": "alice@example.com",
    "location": "Sammamish"
  },
  "sales_data": {                           // Object (pandas DataFrame)
    "2025-11-01": {"product": "A", "units": 10},
    "2025-11-02": {"product": "B", "units": 15}
  },
  "weekly_scores": [                        // Object or Array of Objects (pandas Series)
    {"week": 1, "score": 88},
    {"week": 2, "score": 92},
    {"week": 3, "score": 85}
  ]
}

Tipos de saída suportados

Os tipos de dados de saída suportados são:

Python Tipo de dados
STR
datetime
Bool
int, flutuar
lista[tipo-de-dados], por exemplo lista[int]
dicionário
Nenhum
Série Pandas
Pandas DataFrame

Funções de escrita

Requisitos de sintaxe e limitações

Ao escrever Funções de Dados de Utilizador, deve seguir regras sintáticas específicas para garantir que as suas funções funcionam corretamente.

Nomenclatura dos parâmetros

  • Use camelCase: Os nomes dos parâmetros devem usar a convenção de nomenclatura camelCase e não podem conter sublinhados. Por exemplo, use productName em vez de product_name.
  • Palavras-chave reservadas: Não pode usar palavras-chave reservadas em Python ou as seguintes palavras-chave específicas do Fabric como nomes de parâmetros ou nomes de funções: req, context, e reqInvocationId.

Requisitos de parâmetros

  • Sem valores predefinidos: Os valores dos parâmetros predefinidos não são suportados. Todos os parâmetros são necessários ao invocar uma função. Por exemplo, a seguinte função gera um erro de sintaxe:
    # The default value for the argument called 'name' is not supported and treated like a syntax error.
    @udf.function()
    def goodbye_fabric(name: str = "N/A") -> str:
        return f"Goodbye, {name}."
    
  • Anotações de tipo necessárias: Todos os parâmetros devem incluir anotações de tipo (por exemplo, name: str).

Requisitos de função

  • Tipo de retorno necessário: As funções com o @udf.function() decorador devem especificar uma anotação de tipo de retorno (por exemplo, -> str).
  • Importações obrigatórias: A import fabric.functions as fn instrução e udf = fn.UserDataFunctions() a inicialização são necessárias para que as suas funções funcionem.

Exemplo de sintaxe correta

@udf.function()
def process_order(orderNumber: int, customerName: str, orderDate: str) -> dict:
    return {
        "order_id": orderNumber,
        "customer": customerName,
        "date": orderDate,
        "status": "processed"
    }

Como escrever uma função assíncrona

Adicione decorador assíncrono com sua definição de função em seu código. Com uma async função, você pode melhorar a capacidade de resposta e a eficiência do seu aplicativo lidando com várias tarefas ao mesmo tempo. Eles são ideais para gerenciar grandes volumes de operações vinculadas a E/S. Esta função de exemplo lê um arquivo CSV de uma casa do lago usando pandas. Função usa o nome do arquivo como um parâmetro de entrada.

import pandas as pd 

# Replace the alias "<My Lakehouse alias>" with your connection alias.
@udf.connection(argName="myLakehouse", alias="<My Lakehouse alias>")
@udf.function()
async def read_csv_from_lakehouse(myLakehouse: fn.FabricLakehouseClient, csvFileName: str) -> str:

    # Connect to the Lakehouse
    connection = myLakehouse.connectToFilesAsync()   

    # Download the CSV file from the Lakehouse
    csvFile = connection.get_file_client(csvFileName)

    downloadFile = await csvFile.download_file()
    csvData = await downloadFile.readall()
    
    # Read the CSV data into a pandas DataFrame
    from io import StringIO
    df = pd.read_csv(StringIO(csvData.decode('utf-8')))

    # Display the DataFrame    
    result="" 
    for index, row in df.iterrows():
        result=result + "["+ (",".join([str(item) for item in row]))+"]"
    
    # Close the connection
    csvFile.close()
    connection.close()

    return f"CSV file read successfully.{result}"

Trabalhar com dados

Conexões de dados para fontes de dados Fabric

O SDK permite-lhe referenciar ligações de dados sem necessidade de escrever strings de ligação no seu código. A biblioteca de fabric.functions fornece duas maneiras de lidar com conexões de dados:

  • fabric.functions.FabricSqlConnection: Permite trabalhar com bases de dados SQL no Fabric, incluindo endpoints de SQL Analytics e armazenamentos do Fabric.
  • fabric.functions.FabricLakehouseClient: Permite trabalhar com Lakehouses, oferecendo uma forma de se conectar a tabelas e ficheiros de Lakehouse.

Para fazer referência a uma conexão com uma fonte de dados, precisas usar o decorador @udf.connection. Pode aplicá-lo em qualquer um dos seguintes formatos:

  • @udf.connection(alias="<alias for data connection>", argName="sqlDB")
  • @udf.connection("<alias for data connection>", "<argName>")
  • @udf.connection("<alias for data connection>")

Os argumentos a favor @udf.connection são os seguintes:

  • argName, o nome da variável que a conexão usa em sua função.
  • alias, o alias da conexão que você adicionou com o menu Gerenciar conexões.
  • Se argName e alias tiverem o mesmo valor, você poderá usar @udf.connection("<alias and argName for the data connection>").

Exemplo

# Where demosqldatabase is the argument name and the alias for my data connection used for this function
@udf.connection("demosqldatabase")
@udf.function()
def read_from_sql_db(demosqldatabase: fn.FabricSqlConnection)-> list:
  # Connect to the SQL database
  connection = demosqldatabase.connect()
  cursor = connection.cursor()
  
  # Replace with the query you want to run
  query = "SELECT * FROM (VALUES ('John Smith', 31), ('Kayla Jones', 33)) AS Employee(EmpName, DepID);"
  
  # Execute the query
  cursor.execute(query)
  
  # Fetch all results
  results = cursor.fetchall()
  
  # Close the cursor and connection
  cursor.close()
  connection.close()
  
  return results

Conexões genéricas para itens de malha ou recursos do Azure

O SDK suporta ligações genéricas que permitem criar ligações a itens Fabric ou recursos Azure usando a identidade do proprietário do item User Data Functions. Esse recurso gera um token de ID do Microsoft Entra com a identidade do proprietário do item e um tipo de público fornecido. Esse token é usado para autenticar com itens de malha ou recursos do Azure que dão suporte a esse tipo de público. Esta abordagem proporciona uma experiência de programação semelhante à utilização de objetos de ligações geridas da funcionalidade Gerir Conexões , mas apenas para o tipo de público fornecido na ligação.

Este recurso usa o @udf.generic_connection() decorador com os seguintes parâmetros:

Parâmetro Descrição Valor
argName O nome da variável que é passada para a função. O usuário precisa especificar essa variável nos argumentos de sua função e usar o tipo de fn.FabricItem para ela Por exemplo, se o argName=CosmosDb, então a função deve conter este argumento cosmosDb: fn.FabricItem
audienceType O tipo de público para o qual a conexão é criada. Esse parâmetro está associado ao tipo de item de malha ou serviço do Azure e determina o cliente usado para a conexão. Os valores permitidos para este parâmetro são CosmosDb ou KeyVault.

Conectar-se ao contêiner do Fabric Cosmos DB usando uma conexão genérica

As conexões genéricas suportam itens nativos do Fabric Cosmos DB usando o tipo de público CosmosDB. O SDK de Funções de Dados do Usuário incluído fornece um método auxiliar chamado get_cosmos_client que busca um cliente Cosmos DB singleton para cada invocação.

Você pode se conectar a um item do Fabric Cosmos DB usando uma conexão genérica seguindo estas etapas:

  1. Vai ao portal do Fabric, encontra o teu espaço de trabalho e abre o item de funções de dados do utilizador. Selecione Gestão da Biblioteca, procure a azure-cosmos biblioteca e instale-a. Para mais informações, consulte Gerir bibliotecas.

  2. Vá para as configurações do item do Fabric Cosmos DB .

    Captura de tela mostrando o local do botão de configurações do Fabric Cosmos DB.

  3. Recupere a URL do ponto de extremidade do Fabric Cosmos DB.

    Captura de tela mostrando a URL do ponto de extremidade do Fabric Cosmos DB.

  4. Vá para o item Funções de Dados do Usuário. Use o código de exemplo a seguir para se conectar ao contêiner do Fabric Cosmos DB e executar uma consulta de leitura usando o conjunto de dados de exemplo do Cosmos DB. Substitua os valores das seguintes variáveis:

    • COSMOS_DB_URI com o seu endpoint do Fabric Cosmos DB.
    • DB_NAME com o nome do item do Fabric Cosmos DB.
    from fabric.functions.cosmosdb import get_cosmos_client
    import json
    
    @udf.generic_connection(argName="cosmosDb", audienceType="CosmosDB")
    @udf.function()
    def get_product_by_category(cosmosDb: fn.FabricItem, category: str) -> list:
    
        COSMOS_DB_URI = "YOUR_COSMOS_DB_URL"
        DB_NAME = "YOUR_COSMOS_DB_NAME" # Note: This is the Fabric item name
        CONTAINER_NAME = "SampleData" # Note: This is your container name. In this example, we are using the SampleData container.
    
        cosmosClient = get_cosmos_client(cosmosDb, COSMOS_DB_URI)
    
        # Get the database and container
        database = cosmosClient.get_database_client(DB_NAME)
        container = database.get_container_client(CONTAINER_NAME)
    
        query = 'select * from c WHERE c.category=@category' #"select * from c where c.category=@category"
        parameters = [
            {
                "name": "@category", "value": category
            }
        ]
        results = container.query_items(query=query, parameters=parameters)
        items = [item for item in results]
    
        logging.info(f"Found {len(items)} products in {category}")
    
        return json.dumps(items)
    
  5. Teste ou execute essa função fornecendo um nome de categoria, como Accessory nos parâmetros de invocação.

Observação

Você também pode usar essas etapas para se conectar a um banco de dados do Azure Cosmos DB usando a URL da conta e os nomes do banco de dados. A conta de proprietário das Funções de Dados do Usuário precisaria de permissões para aceder a essa conta do Azure Cosmos DB.

Conectar-se ao Azure Key Vault usando uma conexão genérica

As conexões genéricas suportam conexão a um Cofre de Chaves do Azure usando o tipo de público KeyVault. Esse tipo de conexão requer que o proprietário do Fabric User Data Functions tenha permissões para se conectar ao Cofre de Chaves do Azure. Você pode usar essa conexão para recuperar chaves, segredos ou certificados pelo nome.

Você pode se conectar ao Cofre de Chaves do Azure para recuperar um segredo do cliente para chamar uma API usando uma conexão genérica seguindo estas etapas:

  1. Vai ao portal do Fabric, encontra o teu espaço de trabalho e abre o item de funções de dados do utilizador. Selecione "Gestão de Biblioteca", depois procure e instale as bibliotecas requests e azure-keyvault-secrets. Para mais informações, consulte Gerir bibliotecas.

  2. Acede ao teu recurso Azure Key Vault no portal Azure e recupera o nome da tua chave, segredo ou certificado.

    Captura de ecrã a mostrar a URL e os valores do ponto de extremidade do Azure Key Vault.

  3. Volte para o item Fabric User Data Functions e use este exemplo. Neste exemplo, recuperamos um segredo do Cofre da Chave do Azure para nos conectarmos a uma API pública. Substitua o valor das seguintes variáveis:

    • KEY_VAULT_URL com o Vault URI que recuperaste na fase anterior.
    • KEY_VAULT_SECRET_NAME com o nome do seu segredo.
    • API_URL variável com a URL da API à qual você deseja se conectar. Este exemplo pressupõe que você esteja se conectando a uma API pública que aceita solicitações GET e usa os seguintes parâmetros api-key e request-body.
    from azure.keyvault.secrets import SecretClient
    from azure.identity import DefaultAzureCredential
    import requests
    
    @udf.generic_connection(argName="keyVaultClient", audienceType="KeyVault")
    @udf.function()
    def retrieveNews(keyVaultClient: fn.FabricItem, requestBody:str) -> str:
        KEY_VAULT_URL = 'YOUR_KEY_VAULT_URL'
        KEY_VAULT_SECRET_NAME= 'YOUR_SECRET'
        API_URL = 'YOUR_API_URL'
    
        credential = keyVaultClient.get_access_token()
    
        client = SecretClient(vault_url=KEY_VAULT_URL, credential=credential)
    
        api_key = client.get_secret(KEY_VAULT_SECRET_NAME).value
    
        api_url = API_URL
        params = {
            "api-key": api_key,
            "request-body": requestBody
        }
    
        response = requests.get(api_url, params=params)
    
        data = "" 
    
        if response.status_code == 200:
            data = response.json()
        else:
            print(f"Error {response.status_code}: {response.text}")
    
        return f"Response: {data}"
    
  4. Teste ou execute essa função fornecendo um corpo de solicitação em seu código.

Funcionalidades avançadas

O modelo de programação define padrões avançados que lhe dão maior controlo sobre as suas funções. O SDK implementa estes padrões através de classes e métodos que lhe permitem:

  • Aceda aos metadados de invocação sobre quem chamou a sua função e como
  • Lidar com cenários de erro personalizados com respostas estruturadas ao erro
  • Integrar com bibliotecas de variáveis Fabric para gestão centralizada de configuração

Observação

As Funções de Dados do Utilizador têm limites de serviço para o tamanho do pedido, tempo de expiração de execução e tamanho da resposta. Para detalhes sobre estes limites e como são aplicados, consulte Detalhes e limitações do Serviço.

Obter propriedades de invocação usando UserDataFunctionContext

O SDK inclui o UserDataFunctionContext objeto. Este objeto contém os metadados da invocação da função e pode ser usado para criar lógica de aplicação específica para diferentes mecanismos de invocação (como invocação de portal versus invocação da API REST).

A tabela a seguir mostra as propriedades do objeto UserDataFunctionContext:

Nome da propriedade Tipo de dados Descrição
invocation_id cadeia (de caracteres) O GUID exclusivo vinculado à invocação do item de funções de dados do usuário.
utilizador_em_execução objecto Metadados das informações do usuário usados para autorizar a invocação.

O objeto executing_user contém as seguintes informações:

Nome da propriedade Tipo de dados Descrição
Oide cadeia de caracteres (GUID) O ID do objeto do usuário, que é um identificador imutável para o solicitante. Essa é a identidade verificada do usuário ou da entidade de serviço usada para invocar essa função entre aplicativos.
Id do Locatário cadeia de caracteres (GUID) O ID do inquilino ao qual o utilizador está ligado.
NomeDeUtilizadorPreferido cadeia (de caracteres) O nome de usuário preferido do usuário que invoca, conforme definido pelo usuário. Este valor é mutável.

Para acessar o parâmetro UserDataFunctionContext, você deve usar o seguinte decorador na parte superior da definição da função: @udf.context(argName="<parameter name>")

Exemplo

@udf.context(argName="myContext")
@udf.function()
def getContext(myContext: fabric.functions.UserDataFunctionContext)-> str:
    logging.info('Python UDF trigger function processed a request.')
    return f"Hello oid = {myContext.executing_user['Oid']}, TenantId = {myContext.executing_user['TenantId']}, PreferredUsername = {myContext.executing_user['PreferredUsername']}, InvocationId = {myContext.invocation_id}"

Lançar um erro controlado com UserThrownError

Ao desenvolver a sua função, pode lançar uma resposta de erro esperada usando a UserThrownError classe disponível no SDK. Uma das utilizações desta classe é gerir casos em que as entradas fornecidas pelo utilizador não passam nas regras de validação de negócio.

Exemplo

import datetime

@udf.function()
def raise_userthrownerror(age: int)-> str:
    if age < 18:
        raise fn.UserThrownError("You must be 18 years or older to use this service.", {"age": age})

    return f"Welcome to Fabric Functions at {datetime.datetime.now()}!"

O UserThrownError construtor de classes assume dois parâmetros:

  • Message: Esta cadeia de caracteres é retornada como a mensagem de erro para o aplicativo que está invocando essa função.
  • Um dicionário de propriedades é retornado para o aplicativo que está invocando essa função.

Obter variáveis das bibliotecas de variáveis do Fabric

Uma biblioteca de variáveis Fabric no Microsoft Fabric é um repositório centralizado para gerir variáveis que podem ser usadas entre diferentes itens dentro de um espaço de trabalho. Ele permite que os desenvolvedores personalizem e compartilhem configurações de itens de forma eficiente. Se ainda não tens uma biblioteca de variáveis, vê Criar e gerir bibliotecas de variáveis.

Para usar uma biblioteca de variáveis nas suas funções, adiciona uma ligação a ela a partir do item de funções de dados de utilizador. As bibliotecas de variáveis aparecem no catálogo OneLake juntamente com fontes de dados como bases de dados SQL e lakehouses.

Siga estes passos para usar bibliotecas de variáveis nas suas funções:

  1. No item de funções de dados do utilizador, adicione uma ligação à sua biblioteca de variáveis. No catálogo OneLake, encontre e selecione a sua biblioteca de variáveis, depois selecione Conectar. Note o Alias que o Fabric gera para a ligação.
  2. Adicione um decorador de conexão para o item de biblioteca variável. Por exemplo, @udf.connection(argName="varLib", alias="<My Variable Library Alias>") e substitua o alias para a conexão recém-adicionada para o item de biblioteca variável.
  3. Na definição da função, inclua um argumento com o tipo fn.FabricVariablesClient. Este cliente fornece métodos que você precisa para trabalhar com o item de biblioteca de variáveis.
  4. Use getVariables() o método para obter todas as variáveis da biblioteca de variáveis.
  5. Para ler os valores das variáveis, use ou ["variable-name"] ou .get("variable-name").

Exemplo

Neste exemplo, simulamos um cenário de configuração para um ambiente de produção e de desenvolvimento. Esta função define um caminho de armazenamento dependendo do ambiente selecionado usando um valor recuperado da Biblioteca de Variáveis. A Biblioteca de Variáveis contém uma variável chamada ENV onde os usuários podem definir um valor de dev ou prod.

@udf.connection(argName="varLib", alias="<My Variable Library Alias>")
@udf.function()
def get_storage_path(dataset: str, varLib: fn.FabricVariablesClient) -> str:
    """
    Description: Determine storage path for a dataset based on environment configuration from Variable Library.
    
    Args:
        dataset_name (str): Name of the dataset to store.
        varLib (fn.FabricVariablesClient): Fabric Variable Library connection.
    
    Returns:
        str: Full storage path for the dataset.
    """
    # Retrieve variables from Variable Library
    variables = varLib.getVariables()
    
    # Get environment and base paths
    env = variables.get("ENV")    
    dev_path = variables.get("DEV_FILE_PATH")
    prod_path = variables.get("PROD_FILE_PATH")
    
    # Apply environment-specific logic
    if env.lower() == "dev":
        return f"{dev_path}{dataset}/"
    elif env.lower() == "prod":
        return f"{prod_path}{dataset}/"
    else:
        return f"incorrect settings define for ENV variable"