Funzioni definite dall'utente in Python
Una funzione definita dall'utente (UDF) Python consente di implementare una funzione scalare in Python e utilizzarla in una query SQL. Le funzioni definite dall'utente Python sono simili a quelle SQL e JavaScript, ma con funzionalità aggiuntive. Le UDF Python consentono di installare librerie di terze parti dall'indice dei pacchetti Python (PyPI) e di accedere a servizi esterni utilizzando una connessione alle risorse cloud.
Le UDF Python vengono create ed eseguite su risorse gestite da BigQuery.
Limitazioni
python-3.11
è l'unico runtime supportato.- Non puoi creare una UDF Python temporanea.
- Non puoi utilizzare una UDF Python con una vista materializzata.
- I risultati di una query che chiama una funzione definita dall'utente Python non vengono memorizzati nella cache perché si presume sempre che il valore restituito di una funzione definita dall'utente Python non sia deterministico.
- Le UDF Python non sono completamente supportate nelle visualizzazioni
INFORMATION_SCHEMA
. - Non puoi creare o aggiornare una UDF Python utilizzando l'API Routine.
- I Controlli di servizio VPC non sono supportati.
- Le chiavi di crittografia gestite dal cliente (CMEK) non sono supportate.
- Questi tipi di dati non sono supportati:
JSON
,RANGE
,INTERVAL
eGEOGRAPHY
. - I container che eseguono UDF Python possono essere configurati solo fino a 2 vCPU e 8 Gi.
Ruoli IAM richiesti
I ruoli IAM richiesti dipendono dal fatto che tu sia il proprietario o l'utente di una UDF Python. Il proprietario di una UDF Python in genere crea o aggiorna una UDF. Un utente di UDF Python richiama una UDF creata da un altro utente.
Sono necessari anche ruoli aggiuntivi se crei o esegui una UDF Python che fa riferimento a una connessione di risorsa Cloud.
Proprietari di UDF
Se stai creando o aggiornando una UDF Python, devono essere concessi i seguenti ruoli IAM predefiniti sulla risorsa appropriata:
Ruolo | Autorizzazioni obbligatorie | Risorsa |
---|---|---|
Editor dati BigQuery (roles/bigquery.dataEditor )
|
|
Il set di dati in cui viene creata o aggiornata la UDF Python. |
Utente job BigQuery (roles/bigquery.jobUser )
|
|
Il progetto in cui esegui l'istruzione CREATE FUNCTION .
|
Amministratore connessioni BigQuery (roles/bigquery.connectionAdmin )
|
|
La connessione a cui stai concedendo l'accesso a una risorsa esterna. Questa
connessione è necessaria solo se la tua UDF utilizza la clausola
WITH CONNECTION per
accedere a un servizio esterno.
|
Utenti UDF
Se richiami una UDF Python, devono essere concessi i seguenti ruoli IAM predefiniti sulla risorsa appropriata:
Ruolo | Autorizzazioni obbligatorie | Risorsa |
---|---|---|
Utente BigQuery (roles/bigquery.user ) |
bigquery.jobs.create per eseguire un job di query che fa riferimento alla
UDF. |
Il progetto in cui esegui un job di query che richiama la UDF Python. |
Visualizzatore dati BigQuery (roles/bigquery.dataViewer ) |
bigquery.routines.get per eseguire una UDF creata da qualcun altro. |
Il set di dati in cui è archiviata la UDF Python. |
Utente connessione BigQuery (roles/bigquery.connectionUser ) |
bigquery.connections.use per eseguire una UDF Python che
fa riferimento a una connessione risorsa Cloud. |
La connessione risorsa cloud a cui fa riferimento la UDF Python. Questa connessione è obbligatoria solo se la tua UDF fa riferimento a una connessione. |
Per saperne di più sui ruoli in BigQuery, vedi Ruoli IAM predefiniti.
Crea una funzione definita dall'utente Python permanente
Segui queste regole quando crei una funzione definita dall'utente Python:
Il corpo della UDF Python deve essere un valore letterale stringa tra virgolette che rappresenta il codice Python. Per scoprire di più sui valori letterali stringa tra virgolette, consulta Formati per i valori letterali tra virgolette.
Il corpo della UDF Python deve includere una funzione Python utilizzata nell'argomento
entry_point
nell'elenco delle opzioni della UDF Python.È necessario specificare una versione del runtime Python nell'opzione
runtime_version
. L'unica versione di runtime Python supportata èpython-3.11
. Per un elenco completo delle opzioni disponibili, consulta l'elenco delle opzioni di funzione per l'istruzioneCREATE FUNCTION
.
Per creare una UDF Python persistente, utilizza l'istruzione CREATE FUNCTION
senza la parola chiave TEMP
o TEMPORARY
. Per eliminare una UDF Python permanente,
utilizza l'istruzione DROP FUNCTION
.
Quando crei una UDF Python utilizzando l'istruzione CREATE FUNCTION
,
BigQuery crea o aggiorna un'immagine container basata su
un'immagine di base. Il container viene creato sull'immagine di base utilizzando il tuo codice e tutte le
dipendenze dei pacchetti specificate. La creazione del contenitore è un processo
a esecuzione prolungata. La prima query dopo l'esecuzione dell'istruzione CREATE FUNCTION
potrebbe
attendere automaticamente il completamento dell'immagine. Senza dipendenze esterne,
l'immagine container in genere deve essere creata in meno di un minuto.
Esempio
Per visualizzare un esempio di creazione di una UDF Python persistente, scegli una delle seguenti opzioni:
Console
L'esempio seguente crea una funzione definita dall'utente Python permanente denominata multiplyInputs
e
chiama la funzione definita dall'utente da un'istruzione SELECT
:
Vai alla pagina BigQuery.
Nell'editor di query, inserisci la seguente istruzione
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;
Sostituisci PROJECT_ID.DATASET_ID con l'ID progetto e l'ID set di dati.
Fai clic su
Esegui.Questo esempio produce il seguente output:
+-----+-----+--------------+ | x | y | product | +-----+-----+--------------+ | 1 | 5 | 5.0 | | 2 | 10 | 20.0 | | 3 | 15 | 45.0 | +-----+-----+--------------+
BigQuery DataFrames
L'esempio seguente utilizza BigQuery DataFrames per trasformare una funzione personalizzata in una UDF Python:
Crea una funzione definita dall'utente Python vettorizzata
Puoi implementare la tua funzione definita dall'utente Python per elaborare un batch di righe anziché una singola riga utilizzando la vettorizzazione. La vettorizzazione può migliorare le prestazioni delle query.
Per controllare il comportamento del batch, specifica il numero massimo di righe in ogni batch
utilizzando l'opzione max_batching_rows
nell'elenco di opzioni CREATE OR REPLACE FUNCTION
.
Se specifichi max_batching_rows
, BigQuery determina il numero di righe in un batch, fino al limite di max_batching_rows
. Se max_batching_rows
non è specificato, il numero di righe da raggruppare viene determinato automaticamente.
Una UDF Python vettorizzata ha un singolo argomento pandas.DataFrame
che deve essere annotato. L'argomento pandas.DataFrame
ha lo stesso
numero di colonne dei parametri UDF Python definiti nell'istruzione CREATE FUNCTION
. I nomi delle colonne nell'argomento pandas.DataFrame
hanno gli stessi
nomi dei parametri della UDF.
La funzione deve restituire un pandas.Series
o un pandas.DataFrame
a una sola colonna con lo stesso numero di righe dell'input.
Il seguente esempio crea una funzione definita dall'utente Python vettorizzata denominata multiplyInputs
con due parametri: x
e y
:
Vai alla pagina BigQuery.
Nell'editor di query, inserisci la seguente istruzione
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'] ''';
Sostituisci PROJECT_ID.DATASET_ID con l'ID progetto e l'ID set di dati.
La chiamata alla UDF è la stessa dell'esempio precedente.
Fai clic su
Esegui.
Tipi di dati UDF Python supportati
La seguente tabella definisce il mapping tra i tipi di dati BigQuery, i tipi di dati Python e i tipi di dati Pandas:
Tipo di dati BigQuery | Tipo di dati integrato di Python utilizzato dalla funzione definita dall'utente standard | Tipo di dati Pandas utilizzato dalla funzione definita dall'utente vettorizzata | Tipo di dati PyArrow utilizzato per ARRAY e STRUCT nella UDF vettorizzata |
---|---|---|---|
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 |
Parametro della funzione: Valore restituito dalla funzione: |
Parametro della funzione: Valore restituito dalla funzione: |
TimestampType(timestamp[us]) , con fuso orario |
DATE |
datetime.date |
date32[pyarrow] |
DataType(date32[day]) |
TIME |
datetime.time |
time64[pyarrow] |
Time64Type(time64[us]) |
DATETIME |
datetime.datetime (senza fuso orario) |
timestamp[us][pyarrow] |
TimestampType(timestamp[us]) , senza fuso orario |
ARRAY |
list |
list<...>[pyarrow] , dove il tipo di dati dell'elemento è pandas.ArrowDtype |
ListType |
STRUCT |
dict |
struct<...>[pyarrow] , dove il tipo di dati del campo è pandas.ArrowDtype |
StructType |
Versioni di runtime supportate
Le UDF Python di BigQuery supportano il runtime python-3.11
. Questa
versione di Python include alcuni pacchetti preinstallati aggiuntivi. Per le
librerie di sistema, controlla l'immagine di base del runtime.
Versione runtime | Versione Python | Include | Immagine di base runtime |
---|---|---|---|
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 |
Utilizzare pacchetti di terze parti
Puoi utilizzare l'elenco delle opzioni CREATE FUNCTION
per utilizzare moduli diversi da quelli forniti dalla libreria standard Python
e dai pacchetti preinstallati. Puoi installare pacchetti da Python Package Index (PyPI) oppure importare file Python da Cloud Storage.
Installare un pacchetto dal Python Package Index
Quando installi un pacchetto, devi fornire il nome del pacchetto e, facoltativamente, puoi
fornire la versione del pacchetto utilizzando gli specificatori di versione del pacchetto Python.
Se il pacchetto è nel runtime, viene utilizzato a meno che non venga specificata una versione particolare nell'elenco delle opzioni CREATE FUNCTION
. Se non viene specificata una versione del pacchetto e il pacchetto non è nel runtime, viene utilizzata l'ultima versione disponibile. Sono supportati solo i pacchetti con il formato binario delle ruote.
L'esempio seguente mostra come creare una UDF Python che installa il pacchetto scipy
utilizzando l'elenco di opzioni CREATE OR REPLACE FUNCTION
:
Vai alla pagina BigQuery.
Nell'editor di query, inserisci la seguente istruzione
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);
Sostituisci PROJECT_ID.DATASET_ID con l'ID progetto e l'ID set di dati.
Fai clic su
Esegui.
Importa file Python aggiuntivi come librerie
Puoi estendere le tue UDF Python utilizzando l'elenco delle opzioni di funzione importando file Python da Cloud Storage.
Nel codice Python della tua UDF, puoi importare i file Python da Cloud Storage come moduli utilizzando l'istruzione import seguita dal percorso dell'oggetto Cloud Storage. Ad esempio, se importi
gs://BUCKET_NAME/path/to/lib1.py
, l'istruzione di importazione sarà
import path.to.lib1
.
Il nome file Python deve essere un identificatore Python. Ogni nome folder
nel nome dell'oggetto (dopo /
) deve essere un identificatore Python valido. All'interno dell'intervallo
ASCII (U+0001..U+007F), nei
identificatori possono essere utilizzati i seguenti caratteri:
- Lettere maiuscole e minuscole dalla A alla Z.
- Trattini bassi.
- Le cifre da zero a nove, ma un numero non può essere il primo carattere dell'identificatore.
L'esempio seguente mostra come creare una UDF Python che importa il pacchetto della libreria client lib1.py
da un bucket Cloud Storage denominato my_bucket
:
Vai alla pagina BigQuery.
Nell'editor di query, inserisci la seguente istruzione
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); """;
Sostituisci PROJECT_ID.DATASET_ID con l'ID progetto e l'ID set di dati.
Fai clic su
Esegui.
Configurare i limiti dei container per le UDF Python
Puoi utilizzare l'elenco delle opzioni CREATE FUNCTION
per specificare i limiti di CPU e memoria per i container che eseguono UDF Python.
Per impostazione predefinita, la memoria allocata a ogni istanza container è 512 MiB e la CPU allocata è 0,33 vCPU.
L'esempio seguente crea una UDF Python
utilizzando l'elenco di opzioni CREATE FUNCTION
per specificare i limiti del container:
Vai alla pagina BigQuery.
Nell'editor di query, inserisci la seguente istruzione
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() """;
Sostituisci PROJECT_ID.DATASET_ID con l'ID progetto e l'ID set di dati.
Fai clic su
Esegui.
Valori della CPU supportati
Le UDF Python supportano valori di CPU frazionari compresi tra 0.33
e 1.0
e
valori di CPU non frazionari pari a 1
e 2
. I valori di input frazionari vengono arrotondati a due cifre decimali prima di essere applicati al contenitore.
Valori di memoria supportati
I contenitori UDF Python supportano i valori di memoria nel seguente formato:
<integer_number><unit>
. L'unità deve essere uno di questi valori: Mi
, M
, Gi
,
G
. La quantità minima di memoria che puoi configurare è 256 mebibyte (256 Mi).
La quantità massima di memoria che puoi configurare è 8 gibibyte (8 Gi).
In base al valore di memoria scelto, devi specificare anche la quantità minima di CPU. La tabella seguente mostra i valori minimi della CPU per ogni valore di memoria:
Memoria | CPU minima |
---|---|
512 MiB or less |
0.33 |
More than 512 MiB |
0.5 |
More than 1 GiB |
1 |
More than 4 GiB |
2 |
Chiama Google Cloud o servizi online nel codice Python
Una UDF Python accede a un Google Cloud servizio o a un servizio esterno utilizzando il account di servizio della connessione alle risorse cloud. Al account di servizio della connessione devono essere concesse le autorizzazioni per accedere al servizio. Le autorizzazioni richieste variano a seconda del servizio a cui si accede e delle API chiamate dal codice Python.
Se crei una UDF Python senza utilizzare una connessione a una risorsa Cloud, la funzione viene eseguita in un ambiente che blocca l'accesso alla rete. Se la tua UDF accede a servizi online, devi creare la UDF con una connessione a una risorsa cloud. In caso contrario, l'UDF non potrà accedere alla rete finché non viene raggiunto un timeout della connessione interna.
L'esempio seguente mostra come accedere al servizio Cloud Translation da una UDF Python. Questo esempio ha due progetti: un progetto denominato
my_query_project
in cui crei la UDF e la connessione alla risorsa cloud e un progetto in cui esegui Cloud Translation denominato
my_translate_project
.
Crea una connessione risorsa Cloud
Innanzitutto, crea una connessione risorsa Cloud in my_query_project
. Per creare
la connessione risorsa cloud, segui i passaggi descritti nella pagina Crea una connessione
risorsa cloud.
Dopo aver creato la connessione, aprila e nel riquadro Informazioni sulla connessione, copia l'ID account di servizio. Ti servirà per configurare le autorizzazioni per la connessione. Quando crei una risorsa di connessione, BigQuery crea unaccount di serviziot di sistema univoco e lo associa alla connessione.
Concedi l'accesso al account di servizio della connessione
Per concedere all'account di servizio di connessione delle risorse cloud l'accesso ai tuoi progetti,
concedi all'account di servizio il ruolo di consumer di utilizzo del servizio
(roles/serviceusage.serviceUsageConsumer
) in my_query_project
e il
ruolo di utente API Cloud Translation
(roles/cloudtranslate.user
) in my_translate_project
.
Vai alla pagina IAM.
Verifica che
my_query_project
sia selezionato.Fai clic su
Concedi l'accesso.Nel campo Nuove entità, inserisci l'ID dell'account di servizio della connessione alla risorsa cloud che hai copiato in precedenza.
Nel campo Seleziona un ruolo, scegli Utilizzo del servizio, quindi seleziona Consumer utilizzo del servizio.
Fai clic su Salva.
Nel selettore di progetti, scegli
my_translate_project
.Vai alla pagina IAM.
Fai clic su
Concedi l'accesso.Nel campo Nuove entità, inserisci l'ID dell'account di servizio della connessione alla risorsa cloud che hai copiato in precedenza.
Nel campo Seleziona un ruolo, scegli Cloud Translation e poi seleziona Utente API Cloud Translation.
Fai clic su Salva.
Crea una UDF Python che chiama il servizio Cloud Translation
In my_query_project
, crea una UDF Python che chiami il servizio Cloud Translation utilizzando la connessione alla risorsa cloud.
Vai alla pagina BigQuery.
Inserisci la seguente istruzione
CREATE FUNCTION
nell'editor di query: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;
Sostituisci quanto segue:
PROJECT_ID.DATASET_ID
: il tuo ID progetto e ID datasetREGION.CONNECTION_ID
: la regione e l'ID della connessione
Fai clic su
Esegui.L'output dovrebbe essere simile al seguente:
+--------------------------+-------------------------------+ | text | translated_text | +--------------------------+-------------------------------+ | Hello | Hola | | Good morning | Buen dia | | Goodbye | Adios | +--------------------------+-------------------------------+
Località supportate
Le UDF Python sono supportate in tutte le località regionali e multiregionali BigQuery.
Prezzi
Le UDF Python sono offerte senza costi aggiuntivi.
Quando la fatturazione è abilitata, si applicano le seguenti condizioni:
- I costi delle UDF Python vengono fatturati utilizzando lo SKU dei servizi BigQuery.
- Gli addebiti sono proporzionali alla quantità di calcolo e memoria utilizzati quando viene richiamata la UDF Python.
- Ai clienti delle funzioni definite dall'utente Python viene addebitato anche il costo di creazione o ricreazione dell'immagine container della funzione definita dall'utente. Questo addebito è proporzionale alle risorse utilizzate per creare l'immagine con il codice e le dipendenze del cliente.
- Se le UDF Python generano traffico in uscita dalla rete esterna o da internet, viene visualizzato anche un addebito per il traffico in uscita da internet del livello Premium da Cloud Networking.