Funções definidas pelo utilizador em Python
Uma função definida pelo utilizador (FDU) em Python permite-lhe implementar uma função escalar em Python e usá-la numa consulta SQL. As UDFs Python são semelhantes às UDFs SQL e Javascript, mas com capacidades adicionais. As UDFs Python permitem-lhe instalar bibliotecas de terceiros a partir do Python Package Index (PyPI) e aceder a serviços externos através de uma ligação de recursos do Google Cloud.
As UDFs Python são criadas e executadas em recursos geridos do BigQuery.
Limitações
python-3.11
é o único tempo de execução suportado.- Não pode criar uma UDF Python temporária.
- Não pode usar uma UDF Python com uma vista materializada.
- Os resultados de uma consulta que chama uma FDU Python não são colocados em cache porque o valor de retorno de uma FDU Python é sempre considerado não determinístico.
- As UDFs Python não são totalmente suportadas em
INFORMATION_SCHEMA
vistas. - Não pode criar nem atualizar uma UDF do Python através da API Routine.
- Os VPC Service Controls não são suportados.
- As chaves de encriptação geridas pelo cliente (CMEK) não são suportadas.
- Estes tipos de dados não são suportados:
JSON
,RANGE
,INTERVAL
eGEOGRAPHY
. - Os contentores que executam UDFs Python só podem ser configurados com até 2 vCPUs e 8 Gi.
Funções de IAM necessárias
As funções de IAM necessárias baseiam-se no facto de ser proprietário ou utilizador de uma UDF de Python. Normalmente, um proprietário de UDFs Python cria ou atualiza uma UDF. Um utilizador de UDFs Python invoca uma UDF criada por outra pessoa.
Também são necessárias funções adicionais se criar ou executar uma UDF Python que faça referência a uma ligação de recursos do Google Cloud.
Proprietários de FDUs
Se estiver a criar ou atualizar uma FDU do Python, devem ser concedidas as seguintes funções predefinidas do IAM no recurso adequado:
Função | Autorizações necessárias | Recurso |
---|---|---|
Editor de dados do BigQuery (roles/bigquery.dataEditor )
|
|
O conjunto de dados onde a UDF Python é criada ou atualizada. |
Utilizador de tarefas do BigQuery (roles/bigquery.jobUser )
|
|
O projeto onde está a executar a declaração CREATE FUNCTION .
|
Administrador da ligação do BigQuery (roles/bigquery.connectionAdmin )
|
|
A ligação que está a dar acesso a um recurso externo. Esta ligação só é necessária se a sua FDU usar a cláusula WITH CONNECTION para aceder a um serviço externo.
|
Utilizadores de FDUs
Se estiver a invocar uma FDU Python, devem ser concedidos os seguintes papéis do IAM predefinidos no recurso adequado:
Função | Autorizações necessárias | Recurso |
---|---|---|
Utilizador do BigQuery (roles/bigquery.user ) |
bigquery.jobs.create para executar uma tarefa de consulta que faça referência à UDF. |
O projeto onde está a executar uma tarefa de consulta que invoca a UDF Python. |
Visualizador de dados do BigQuery (roles/bigquery.dataViewer ) |
bigquery.routines.get para executar uma FDU criada por outra pessoa. |
O conjunto de dados onde a UDF Python está armazenada. |
Utilizador de ligação do BigQuery (roles/bigquery.connectionUser ) |
bigquery.connections.use para executar uma UDF Python que
faça referência a uma ligação de recursos da nuvem. |
A ligação de recursos da nuvem referenciada pela UDF de Python. Esta ligação só é necessária se a sua FDU referenciar uma ligação. |
Para mais informações sobre as funções no BigQuery, consulte o artigo Funções do IAM predefinidas.
Crie uma FDU Python persistente
Siga estas regras quando criar uma FDU do Python:
O corpo da UDF Python tem de ser um literal de string entre aspas que represente o código Python. Para saber mais sobre os literais de strings entre aspas, consulte Formatos para literais entre aspas.
O corpo da FDU Python tem de incluir uma função Python que é usada no argumento
entry_point
na lista de opções da FDU Python.Tem de especificar uma versão de tempo de execução do Python na opção
runtime_version
. A única versão do tempo de execução do Python suportada é apython-3.11
. Para ver uma lista completa das opções disponíveis, consulte a lista de opções de funções para a declaraçãoCREATE FUNCTION
.
Para criar uma FDU Python persistente, use a declaração CREATE FUNCTION
sem a palavra-chave TEMP
ou TEMPORARY
. Para eliminar uma UDF Python persistente,
use a declaração DROP FUNCTION
.
Quando cria uma FDU Python com a declaração CREATE FUNCTION
, o BigQuery cria ou atualiza uma imagem de contentor baseada numa imagem base. O contentor é criado na imagem de base com o seu código e todas as dependências de pacotes especificadas. A criação do contentor é um processo de longa duração. A primeira consulta após executar a declaração CREATE FUNCTION
pode aguardar automaticamente que a imagem seja concluída. Sem dependências externas, a imagem do contentor deve ser criada, normalmente, em menos de um minuto.
Exemplo
Para ver um exemplo de criação de uma UDF Python persistente, escolha uma das seguintes opções:
Consola
O exemplo seguinte cria uma FDU Python persistente com o nome multiplyInputs
e
chama a FDU a partir de uma declaração SELECT
:
Aceda à página do BigQuery.
No editor de consultas, introduza a seguinte declaração
CREATE FUNCTION
:CREATE FUNCTION `PROJECT_ID.DATASET_ID`.multiplyInputs(x FLOAT64, y FLOAT64) RETURNS FLOAT64 LANGUAGE python OPTIONS(runtime_version="python-3.11", entry_point="multiply") AS r''' def multiply(x, y): return x * y '''; -- Call the Python UDF. WITH numbers AS (SELECT 1 AS x, 5 as y UNION ALL SELECT 2 AS x, 10 as y UNION ALL SELECT 3 as x, 15 as y) SELECT x, y, `PROJECT_ID.DATASET_ID`.multiplyInputs(x, y) AS product FROM numbers;
Substituir PROJECT_ID.DATASET_ID com o ID do projeto e o ID do conjunto de dados.
Clique em
Executar.Este exemplo produz o seguinte resultado:
+-----+-----+--------------+ | x | y | product | +-----+-----+--------------+ | 1 | 5 | 5.0 | | 2 | 10 | 20.0 | | 3 | 15 | 45.0 | +-----+-----+--------------+
DataFrames do BigQuery
O exemplo seguinte usa DataFrames do BigQuery para transformar uma função personalizada numa UDF do Python:
Crie uma FDU do Python vetorizada
Pode implementar a sua FDU Python para processar um lote de linhas em vez de uma única linha usando a vetorização. A vetorização pode melhorar o desempenho das consultas.
Para controlar o comportamento de processamento em lote, especifique o número máximo de linhas em cada lote
usando a opção max_batching_rows
na CREATE OR REPLACE FUNCTION
lista de opções.
Se especificar max_batching_rows
, o BigQuery determina o número de linhas num lote, até ao limite de max_batching_rows
. Se max_batching_rows
não for especificado, o número de linhas a processar em lote é determinado automaticamente.
Uma FDU Python vetorizada tem um único argumento pandas.DataFrame
que tem de ser anotado. O argumento pandas.DataFrame
tem o mesmo número de colunas que os parâmetros da UDF Python definidos na declaração CREATE FUNCTION
. Os nomes das colunas no argumento pandas.DataFrame
têm os mesmos nomes que os parâmetros da FDU.
A sua função tem de devolver um pandas.Series
ou um pandas.DataFrame
de coluna única com o mesmo número de linhas que a entrada.
O exemplo seguinte cria uma UDF do Python vetorizada denominada multiplyInputs
com dois parâmetros: x
e y
:
Aceda à página do BigQuery.
No editor de consultas, introduza a seguinte declaração
CREATE FUNCTION
:CREATE FUNCTION `PROJECT_ID.DATASET_ID`.multiplyVectorized(x FLOAT64, y FLOAT64) RETURNS FLOAT64 LANGUAGE python OPTIONS(runtime_version="python-3.11", entry_point="vectorized_multiply") AS r''' import pandas as pd def vectorized_multiply(df: pd.DataFrame): return df['x'] * df['y'] ''';
Substituir PROJECT_ID.DATASET_ID com o ID do projeto e o ID do conjunto de dados.
A chamada da FDU é igual à do exemplo anterior.
Clique em
Executar.
Tipos de dados de FDU do Python suportados
A tabela seguinte define o mapeamento entre os tipos de dados do BigQuery, os tipos de dados do Python e os tipos de dados do Pandas:
Tipo de dados do BigQuery | Tipo de dados incorporado do Python usado pela FDU padrão | Tipo de dados Pandas usado pela FDU vetorizada | Tipo de dados PyArrow usado para ARRAY e STRUCT na UDF vetorizada |
---|---|---|---|
BOOL |
bool |
BooleanDtype |
DataType(bool) |
INT64 |
int |
Int64Dtype |
DataType(int64) |
FLOAT64 |
float |
FloatDtype |
DataType(double) |
STRING |
str |
StringDtype |
DataType(string) |
BYTES |
bytes |
binary[pyarrow] |
DataType(binary) |
TIMESTAMP |
Parâmetro da função: Valor de devolução da função: |
Parâmetro da função: Valor devolvido da função: |
TimestampType(timestamp[us]) , com fuso horário |
DATE |
datetime.date |
date32[pyarrow] |
DataType(date32[day]) |
TIME |
datetime.time |
time64[pyarrow] |
Time64Type(time64[us]) |
DATETIME |
datetime.datetime (sem fuso horário) |
timestamp[us][pyarrow] |
TimestampType(timestamp[us]) , sem fuso horário |
ARRAY |
list |
list<...>[pyarrow] , em que o tipo de dados do elemento é pandas.ArrowDtype |
ListType |
STRUCT |
dict |
struct<...>[pyarrow] , em que o tipo de dados do campo é pandas.ArrowDtype |
StructType |
Versões do tempo de execução suportadas
As UDFs Python do BigQuery suportam o tempo de execução python-3.11
. Esta versão do Python inclui alguns pacotes pré-instalados adicionais. Para bibliotecas do sistema, verifique a imagem base de tempo de execução.
Versão do tempo de execução | Versão do Python | Inclui | Imagem base do tempo de execução |
---|---|---|---|
python-3.11 | Python 3.11 | numpy 1.26.3 pyarrow 14.0.2 pandas 2.1.4 python-dateutil 2.8.2 |
google-22-full/python311 |
Use pacotes de terceiros
Pode usar a CREATE FUNCTION
lista de opções
para usar módulos que não sejam os fornecidos pela biblioteca padrão do Python
e pacotes pré-instalados. Pode instalar pacotes do Python Package Index (PyPI) ou importar ficheiros Python do Cloud Storage.
Instale um pacote a partir do índice de pacotes do Python
Quando instala um pacote, tem de indicar o nome do pacote e, opcionalmente, pode indicar a versão do pacote através dos especificadores de versão do pacote Python.
Se o pacote estiver no tempo de execução, esse pacote é usado, a menos que seja especificada uma versão específica na lista de opções CREATE FUNCTION
. Se não for especificada uma versão do pacote e o pacote não estiver no tempo de execução, é usada a versão mais recente disponível. Apenas são suportados pacotes com o formato binário de rodas.
O exemplo seguinte mostra como criar uma FDU Python que instala o pacote scipy
usando a lista de opções CREATE OR REPLACE FUNCTION
:
Aceda à página do BigQuery.
No editor de consultas, introduza a seguinte declaração
CREATE FUNCTION
:CREATE FUNCTION `PROJECT_ID.DATASET_ID`.area(radius FLOAT64) RETURNS FLOAT64 LANGUAGE python OPTIONS (entry_point='area_handler', runtime_version='python-3.11', packages=['scipy==1.15.3']) AS r""" import scipy def area_handler(radius): return scipy.constants.pi*radius*radius """; SELECT `PROJECT_ID.DATASET_ID`.area(4.5);
Substituir PROJECT_ID.DATASET_ID com o ID do projeto e o ID do conjunto de dados.
Clique em
Executar.
Importe ficheiros Python adicionais como bibliotecas
Pode estender as suas UDFs Python através da lista de opções de funções importando ficheiros Python do Cloud Storage.
No código Python da UDF, pode importar os ficheiros Python do Cloud Storage como módulos usando a declaração import seguida do caminho para o objeto do Cloud Storage. Por exemplo, se estiver a importar
gs://BUCKET_NAME/path/to/lib1.py
, a declaração de importação seria
import path.to.lib1
.
O nome do ficheiro Python tem de ser um identificador Python. Cada nome folder
no nome do objeto (após /
) deve ser um identificador Python válido. Dentro do intervalo ASCII (U+0001..U+007F), podem ser usados os seguintes carateres em identificadores:
- Letras maiúsculas e minúsculas de A a Z.
- Sublinhados.
- Os dígitos de zero a nove, mas um número não pode aparecer como o primeiro caráter no identificador.
O exemplo seguinte mostra como criar uma UDF Python que importa o pacote da biblioteca cliente lib1.py
de um contentor do Cloud Storage denominado my_bucket
:
Aceda à página do BigQuery.
No editor de consultas, introduza a seguinte declaração
CREATE FUNCTION
:CREATE FUNCTION `PROJECT_ID.DATASET_ID`.myFunc(a FLOAT64, b STRING) RETURNS STRING LANGUAGE python OPTIONS ( entry_point='compute', runtime_version='python-3.11', library=['gs://my_bucket/path/to/lib1.py']) AS r""" import path.to.lib1 as lib1 def compute(a, b): # doInterestingStuff is a function defined in # gs://my_bucket/path/to/lib1.py return lib1.doInterestingStuff(a, b); """;
Substituir PROJECT_ID.DATASET_ID com o ID do projeto e o ID do conjunto de dados.
Clique em
Executar.
Configure limites de contentores para FDU do Python
Pode usar a lista de opções
para especificar limites de CPU e memória para contentores que executam UDFs Python.CREATE FUNCTION
Por predefinição, a memória alocada a cada instância de contentor é de 512 MiB e a CPU alocada é de 0,33 vCPU.
O exemplo seguinte cria uma FDU do Python
usando a lista de opções CREATE FUNCTION
para especificar limites de contentores:
Aceda à página do BigQuery.
No editor de consultas, introduza a seguinte declaração
CREATE FUNCTION
:CREATE FUNCTION `PROJECT_ID.DATASET_ID`.resizeImage(image BYTES) RETURNS BYTES LANGUAGE python OPTIONS (entry_point='resize_image', runtime_version='python-3.11', packages=['Pillow==11.2.1'], container_memory='2Gi', container_cpu=1) AS r""" import io from PIL import Image def resize_image(image_bytes): img = Image.open(io.BytesIO(image_bytes)) resized_img = img.resize((256, 256), Image.Resampling.LANCZOS) output_stream = io.BytesIO() resized_img.convert('RGB').save(output_stream, format='JPEG') return output_stream.getvalue() """;
Substituir PROJECT_ID.DATASET_ID com o ID do projeto e o ID do conjunto de dados.
Clique em
Executar.
Valores de CPU suportados
As UDFs Python suportam valores fracionários da CPU entre 0.33
e 1.0
e valores não fracionários da CPU de 1
e 2
. Os valores de entrada fracionários são arredondados para duas casas decimais antes de serem aplicados ao contentor.
Valores de memória suportados
Os contentores de FDU do Python suportam valores de memória no seguinte formato:
<integer_number><unit>
. A unidade tem de ser um destes valores: Mi
, M
, Gi
,
G
. A quantidade mínima de memória que pode configurar é de 256 Mebibytes (256 Mi).
A quantidade máxima de memória que pode configurar é de 8 gibibytes (8 Gi).
Com base no valor de memória que escolher, também tem de especificar a quantidade mínima de CPU. A tabela seguinte mostra os valores mínimos da CPU para cada valor de memória:
Memória | CPU mínima |
---|---|
512 MiB or less |
0.33 |
More than 512 MiB |
0.5 |
More than 1 GiB |
1 |
More than 4 GiB |
2 |
Chame Trusted Cloud by S3NS serviços online em código Python
Uma UDF do Python acede a um Trusted Cloud by S3NS serviço ou a um serviço externo através da conta de serviço daligação de recursos do Google Cloud. É necessário conceder autorizações à conta de serviço da associação para aceder ao serviço. As autorizações necessárias variam consoante o serviço acedido e as APIs chamadas a partir do seu código Python.
Se criar uma FDU Python sem usar uma ligação de recursos da nuvem, a função é executada num ambiente que bloqueia o acesso à rede. Se a sua FDU aceder a serviços online, tem de criar a FDU com uma ligação de recursos da nuvem. Caso contrário, a FDU fica impedida de aceder à rede até atingir um limite de tempo de ligação interno.
O exemplo seguinte mostra como aceder ao serviço Cloud Translation
a partir de uma UDF Python. Este exemplo tem dois projetos: um projeto denominado my_query_project
, onde cria a UDF e a associação de recursos da nuvem, e um projeto onde está a executar o Cloud Translation denominado my_translate_project
.
Crie uma associação de recursos da nuvem
Primeiro, cria uma associação de recursos da nuvem em my_query_project
. Para criar a associação de recursos da nuvem, siga os passos na página Criar uma associação de recursos da nuvem.
Depois de criar a associação, abra-a e, no painel Informações de associação, copie o ID da conta de serviço. Precisa deste ID quando configura as autorizações para a ligação. Quando cria um recurso de ligação, o BigQuery cria uma conta de serviço do sistema exclusiva e associa-a à ligação.
Conceda acesso à conta de serviço da associação
Para conceder à conta de serviço de ligação de recursos da nuvem acesso aos seus projetos,
conceda à conta de serviço a função de consumidor de utilização de serviços
(roles/serviceusage.serviceUsageConsumer
) em my_query_project
e a
função de utilizador da API Cloud Translation
(roles/cloudtranslate.user
) em my_translate_project
.
Aceda à página IAM.
Verifique se a opção
my_query_project
está selecionada.Clique em
Conceder acesso.No campo Novos membros, introduza o ID da conta de serviço da associação de recursos do Google Cloud que copiou anteriormente.
No campo Selecionar uma função, escolha Utilização do serviço e, de seguida, selecione Consumidor de utilização do serviço.
Clique em Guardar.
No seletor de projetos, escolha
my_translate_project
.Aceda à página IAM.
Clique em
Conceder acesso.No campo Novos membros, introduza o ID da conta de serviço da associação de recursos do Google Cloud que copiou anteriormente.
No campo Selecionar uma função, escolha Cloud Translation e, de seguida, selecione Utilizador da Cloud Translation API.
Clique em Guardar.
Crie uma FDU Python que chame o serviço Cloud Translation
No my_query_project
, crie uma UDF Python que chame o serviço Cloud Translation
usando a sua ligação de recursos do Google Cloud.
Aceda à página do BigQuery.
Introduza a seguinte declaração
CREATE FUNCTION
no editor de consultas:CREATE FUNCTION `PROJECT_ID.DATASET_ID`.translate_to_es(x STRING) RETURNS STRING LANGUAGE python WITH CONNECTION `PROJECT_ID.REGION.CONNECTION_ID` OPTIONS (entry_point='do_translate', runtime_version='python-3.11', packages=['google-cloud-translate>=3.11', 'google-api-core']) AS r""" from google.api_core.retry import Retry from google.cloud import translate project = "my_translate_project" translate_client = translate.TranslationServiceClient() def do_translate(x : str) -> str: response = translate_client.translate_text( request={ "parent": f"projects/{project}/locations/us-central1", "contents": [x], "target_language_code": "es", "mime_type": "text/plain", }, retry=Retry(), ) return response.translations[0].translated_text """; -- Call the UDF. WITH text_table AS (SELECT "Hello" AS text UNION ALL SELECT "Good morning" AS text UNION ALL SELECT "Goodbye" AS text) SELECT text, `PROJECT_ID.DATASET_ID`.translate_to_es(text) AS translated_text FROM text_table;
Substitua o seguinte:
PROJECT_ID.DATASET_ID
: o ID do projeto e o ID do conjunto de dadosREGION.CONNECTION_ID
: a região e o ID da sua ligação
Clique em
Executar.O resultado deve ter o seguinte aspeto:
+--------------------------+-------------------------------+ | text | translated_text | +--------------------------+-------------------------------+ | Hello | Hola | | Good morning | Buen dia | | Goodbye | Adios | +--------------------------+-------------------------------+
Localizações suportadas
As UDFs Python são suportadas em todas as localizações regionais e multirregionais do BigQuery.
Preços
As UDFs Python são oferecidas sem custos adicionais.
Quando a faturação está ativada, aplicam-se as seguintes condições:
- Os custos das UDFs Python são faturados através do SKU dos serviços do BigQuery.
- As cobranças são proporcionais à quantidade de computação e memória consumidas quando a UDF Python é invocada.
- Os clientes de FDU do Python também pagam o custo de criação ou recriação da imagem do contentor da FDU. Este custo é proporcional aos recursos usados para criar a imagem com o código do cliente e as dependências.
- Se as UDFs Python resultarem em saída de rede externa ou de Internet, também vê um custo de saída de Internet do Nível Premium da Cloud Networking.