Benutzerdefinierte Funktionen in Python
Mit einer benutzerdefinierten Python-Funktion (User-Defined Function, UDF) können Sie eine Skalarfunktion in Python implementieren und in einer SQL-Abfrage verwenden. Python-UDFs ähneln SQL- und JavaScript-UDFs, bieten aber zusätzliche Funktionen. Mit Python-UDFs können Sie Bibliotheken von Drittanbietern aus dem Python Package Index (PyPI) installieren und über eine Cloud-Ressourcenverbindung auf externe Dienste zugreifen.
Python-UDFs werden in BigQuery verwalteten Ressourcen erstellt und ausgeführt.
Beschränkungen
python-3.11
ist die einzige unterstützte Laufzeit.- Sie können keine temporäre Python-UDF erstellen.
- Sie können keine Python-UDFs mit einer materialisierten Ansicht verwenden.
- Die Ergebnisse einer Abfrage, die eine Python-UDF aufruft, werden nicht im Cache gespeichert, da der Rückgabewert einer Python-UDF immer als nicht deterministisch angenommen wird.
- Python-UDFs werden in
INFORMATION_SCHEMA
-Ansichten nicht vollständig unterstützt. - Mit der Routine API können Sie keine Python-UDFs erstellen oder aktualisieren.
- VPC Service Controls werden nicht unterstützt.
- Vom Kunden verwaltete Verschlüsselungsschlüssel (CMEK) werden nicht unterstützt.
- Die folgenden Datentypen werden nicht unterstützt:
JSON
,RANGE
,INTERVAL
undGEOGRAPHY
.
Erforderliche IAM-Rollen
Die erforderlichen IAM-Rollen hängen davon ab, ob Sie Inhaber oder Nutzer einer benutzerdefinierten Python-Funktion sind. Der Inhaber einer Python-UDF erstellt oder aktualisiert in der Regel eine UDF. Ein Python-UDF-Nutzer ruft eine UDF auf, die von einem anderen Nutzer erstellt wurde.
Zusätzliche Rollen sind auch erforderlich, wenn Sie eine Python-UDF erstellen oder ausführen, die auf eine Cloud-Ressourcenverbindung verweist.
UDF-Inhaber
Wenn Sie eine Python-UDF erstellen oder aktualisieren, sollten der entsprechenden Ressource die folgenden vordefinierten IAM-Rollen zugewiesen werden:
Rolle | Erforderliche Berechtigungen | Ressource |
---|---|---|
BigQuery Data Editor (roles/bigquery.dataEditor )
|
|
Das Dataset, in dem die Python-UDF erstellt oder aktualisiert wird. |
BigQuery-Jobnutzer (roles/bigquery.jobUser )
|
|
Das Projekt, in dem Sie die CREATE FUNCTION -Anweisung ausführen.
|
BigQuery Connection Admin (roles/bigquery.connectionAdmin )
|
|
Die Verbindung, über die Sie einer externen Ressource Zugriff gewähren. Diese Verbindung ist nur erforderlich, wenn Ihre UDF die Klausel WITH CONNECTION zum Zugriff auf einen externen Dienst verwendet.
|
UDF-Nutzer
Wenn Sie eine Python-UDF aufrufen, sollten der entsprechenden Ressource die folgenden vordefinierten IAM-Rollen zugewiesen werden:
Rolle | Erforderliche Berechtigungen | Ressource |
---|---|---|
BigQuery-Nutzer (roles/bigquery.user ) |
bigquery.jobs.create , um einen Abfragejob auszuführen, der auf die UDF verweist. |
Das Projekt, in dem Sie einen Abfragejob ausführen, der die Python-UDF aufruft. |
BigQuery-Datenbetrachter (roles/bigquery.dataViewer ) |
bigquery.routines.get , um eine von einer anderen Person erstellte UDF auszuführen. |
Der Datensatz, in dem die Python-UDF gespeichert ist. |
BigQuery-Verbindungsnutzer (roles/bigquery.connectionUser ) |
bigquery.connections.use , um eine Python-UDF auszuführen, die auf eine Cloud-Ressourcenverbindung verweist. |
Die Cloud-Ressourcenverbindung, auf die das Python-UDF verweist. Diese Verbindung ist nur erforderlich, wenn Ihre UDF auf eine Verbindung verweist. |
Weitere Informationen zu Rollen in BigQuery finden Sie unter Vordefinierte IAM-Rollen.
Nichtflüchtiges Python-UDF erstellen
Beachten Sie beim Erstellen einer Python-UDF die folgenden Regeln:
Der Textkörper der Python-UDF muss ein in Anführungszeichen gesetztes Stringliteral sein, das den Python-Code darstellt. Weitere Informationen zu Stringliteralen in Anführungszeichen finden Sie unter Formate für Stringliterale in Anführungszeichen.
Der Body der Python-UDF muss eine Python-Funktion enthalten, die in der Liste der Python-UDF-Optionen im Argument
entry_point
verwendet wird.In der Option
runtime_version
muss eine Python-Laufzeitversion angegeben werden. Die einzige unterstützte Python-Laufzeitversion istpython-3.11
. Eine vollständige Liste der verfügbaren Optionen finden Sie in der Liste der Funktionsoptionen für die AnweisungCREATE FUNCTION
.
Verwenden Sie zum Erstellen einer nichtflüchtigen Python-UDF die Anweisung CREATE FUNCTION
ohne das Schlüsselwort TEMP
oder TEMPORARY
. Verwenden Sie die Anweisung DROP FUNCTION
, um eine persistente Python-UDF zu löschen.
Wenn Sie eine Python-UDF mit der CREATE FUNCTION
-Anweisung erstellen, erstellt oder aktualisiert BigQuery ein Container-Image, das auf einem Basis-Image basiert. Der Container wird auf dem Basis-Image mit Ihrem Code und allen angegebenen Paketabhängigkeiten erstellt. Das Erstellen des Containers ist ein langwieriger Vorgang. Bei der ersten Abfrage nach dem Ausführen der CREATE FUNCTION
-Anweisung wird möglicherweise automatisch gewartet, bis das Bild fertig ist. Ohne externe Abhängigkeiten sollte das Container-Image in der Regel in weniger als einer Minute erstellt werden.
Beispiel
Wählen Sie eine der folgenden Optionen aus, um ein Beispiel für das Erstellen einer persistenten Python-UDF zu sehen:
Console
Im folgenden Beispiel wird eine persistente Python-UDF mit dem Namen multiplyInputs
erstellt und die UDF aus einer SELECT
-Anweisung aufgerufen:
Rufen Sie die Seite BigQuery auf.
Geben Sie im Abfrageeditor die folgende
CREATE FUNCTION
-Anweisung ein: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;
Ersetzen Sie PROJECT_ID.DATASET_ID durch Ihre Projekt-ID und Dataset-ID.
Klicken Sie auf
Ausführen.Dieses Beispiel liefert folgende Ausgabe:
+-----+-----+--------------+ | x | y | product | +-----+-----+--------------+ | 1 | 5 | 5.0 | | 2 | 10 | 20.0 | | 3 | 15 | 45.0 | +-----+-----+--------------+
BigQuery DataFrames
Im folgenden Beispiel wird eine benutzerdefinierte Funktion mit BigQuery DataFrames in eine Python-UDF umgewandelt:
Vektorisierte Python-UDF erstellen
Mithilfe der vektoriellen Verarbeitung können Sie Ihre Python-UDF so implementieren, dass eine Reihe von Zeilen anstelle einer einzelnen Zeile verarbeitet wird. Die Vektorisierung kann die Abfrageleistung verbessern.
Um das Batch-Verhalten zu steuern, geben Sie mit der Option max_batching_rows
in der Optionsliste CREATE OR REPLACE FUNCTION
die maximale Anzahl von Zeilen in jedem Batch an.
Wenn Sie max_batching_rows
angeben, bestimmt BigQuery die Anzahl der Zeilen in einem Batch bis zum Limit von max_batching_rows
. Wenn max_batching_rows
nicht angegeben ist, wird die Anzahl der Zeilen für den Batch automatisch ermittelt.
Eine vektorisierte Python-UDF hat ein einzelnes pandas.DataFrame
-Argument, das annotiert werden muss. Das Argument pandas.DataFrame
hat dieselbe Anzahl von Spalten wie die Python-UDF-Parameter, die in der CREATE FUNCTION
-Anweisung definiert sind. Die Spaltennamen im Argument pandas.DataFrame
haben dieselben Namen wie die Parameter der UDF.
Ihre Funktion muss entweder eine pandas.Series
oder eine pandas.DataFrame
mit einer einzelnen Spalte mit derselben Anzahl von Zeilen wie die Eingabe zurückgeben.
Im folgenden Beispiel wird eine vektorisierte Python-UDF mit dem Namen multiplyInputs
mit zwei Parametern erstellt: x
und y
:
Rufen Sie die Seite BigQuery auf.
Geben Sie im Abfrageeditor die folgende
CREATE FUNCTION
-Anweisung ein: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'] ''';
Ersetzen Sie PROJECT_ID.DATASET_ID durch Ihre Projekt-ID und Dataset-ID.
Der Aufruf der UDF erfolgt wie im vorherigen Beispiel.
Klicken Sie auf
Ausführen.
Von Python-UDFs unterstützte Datentypen
In der folgenden Tabelle wird die Zuordnung zwischen BigQuery-Datentypen, Python-Datentypen und Pandas-Datentypen definiert:
BigQuery-Datentyp | In Python integrierter Datentyp, der von Standard-UDFs verwendet wird | Pandas-Datentyp, der von vektorisierten UDFs verwendet wird | PyArrow-Datentyp, der für ARRAY und STRUCT in vektorisierten UDFs verwendet wird |
---|---|---|---|
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 |
Funktionsparameter: Rückgabewert der Funktion: |
Funktionsparameter: Rückgabewert der Funktion: |
TimestampType(timestamp[us]) , mit Zeitzone |
DATE |
datetime.date |
date32[pyarrow] |
DataType(date32[day]) |
TIME |
datetime.time |
time64[pyarrow] |
Time64Type(time64[us]) |
DATETIME |
datetime.datetime (ohne Zeitzone) |
timestamp[us][pyarrow] |
TimestampType(timestamp[us]) , ohne Zeitzone |
ARRAY |
list |
list<...>[pyarrow] , wobei der Elementdatentyp ein pandas.ArrowDtype ist |
ListType |
STRUCT |
dict |
struct<...>[pyarrow] , wobei der Felddatentyp pandas.ArrowDtype ist |
StructType |
Unterstützte Laufzeitversionen
BigQuery-Python-UDFs unterstützen die python-3.11
-Laufzeit. Diese Python-Version enthält einige zusätzliche vorinstallierte Pakete. Informationen zu Systembibliotheken finden Sie im Laufzeit-Basis-Image.
Laufzeitversion | Python-Version | Enthält | Laufzeit-Basis-Image |
---|---|---|---|
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 |
Drittanbieterpakete verwenden
Mit der Optionsliste CREATE FUNCTION
können Sie andere Module als die der Python-Standardbibliothek und vorinstallierten Pakete verwenden. Sie können Pakete aus dem Python-Paketindex (PyPI) installieren oder Python-Dateien aus Cloud Storage importieren.
Paket aus dem Python Package Index installieren
Wenn Sie ein Paket installieren, müssen Sie den Paketnamen angeben. Optional können Sie auch die Paketversion mithilfe von Python-Versionsangaben angeben.
Wenn sich das Paket in der Laufzeit befindet, wird es verwendet, es sei denn, in der Optionsliste CREATE FUNCTION
ist eine bestimmte Version angegeben. Wenn keine Paketversion angegeben ist und das Paket nicht in der Laufzeit enthalten ist, wird die neueste verfügbare Version verwendet. Es werden nur Pakete im Binary-Format von Wheels unterstützt.
Im folgenden Beispiel wird gezeigt, wie Sie eine Python-UDF erstellen, mit der das Clientbibliothekspaket der Cloud Translation API mithilfe der Optionsliste CREATE OR REPLACE FUNCTION
installiert wird:
Rufen Sie die Seite BigQuery auf.
Geben Sie im Abfrageeditor die folgende
CREATE FUNCTION
-Anweisung ein:CREATE FUNCTION `PROJECT_ID.DATASET_ID`.translate(src STRING) RETURNS STRING LANGUAGE python OPTIONS (entry_point='do_translate', runtime_version='python-3.11', packages=['google-cloud-translate>=3.11']) AS r""" from google.cloud import translate def do_translate(src): # See the example in following section for the detail guide and # the implementation return """;
Ersetzen Sie PROJECT_ID.DATASET_ID durch Ihre Projekt-ID und Dataset-ID.
Klicken Sie auf
Ausführen.
Zusätzliche Python-Dateien als Bibliotheken importieren
Sie können Ihre Python-UDFs über die Liste der Funktionsoptionen erweitern, indem Sie Python-Dateien aus Cloud Storage importieren.
Im Python-Code Ihrer UDF können Sie die Python-Dateien aus Cloud Storage als Module importieren. Verwenden Sie dazu den Importbefehl gefolgt vom Pfad zum Cloud Storage-Objekt. Wenn Sie beispielsweise gs://BUCKET_NAME/path/to/lib1.py
importieren, lautet die Importanweisung import path.to.lib1
.
Der Python-Dateiname muss eine Python-Kennzeichnung sein. Jeder folder
-Name im Objektnamen (nach dem /
) muss eine gültige Python-Kennzeichnung sein. Im ASCII-Bereich (U+0001..U+007F) können die folgenden Zeichen in Bezeichnern verwendet werden:
- Groß- und Kleinbuchstaben A bis Z
- Unterstriche
- Die Ziffern 0 bis 9, wobei eine Zahl nicht als erstes Zeichen in der Kennung erscheinen darf.
Im folgenden Beispiel wird gezeigt, wie Sie eine Python-UDF erstellen, die das Clientbibliothekspaket lib1.py
aus einem Cloud Storage-Bucket namens my_bucket
importiert:
Rufen Sie die Seite BigQuery auf.
Geben Sie im Abfrageeditor die folgende
CREATE FUNCTION
-Anweisung ein: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); """;
Ersetzen Sie PROJECT_ID.DATASET_ID durch Ihre Projekt-ID und Dataset-ID.
Klicken Sie auf
Ausführen.
Google Cloud oder Onlinedienste in Python-Code aufrufen
Ein Python-UDF greift über das Dienstkonto der Cloud-Ressourcenverbindung auf einen Google Cloud Dienst oder einen externen Dienst zu. Dem Dienstkonto der Verbindung müssen Berechtigungen für den Zugriff auf den Dienst gewährt werden. Die erforderlichen Berechtigungen variieren je nach dem Dienst, auf den zugegriffen wird, und den APIs, die über Ihren Python-Code aufgerufen werden.
Wenn Sie eine Python-UDF erstellen, ohne eine Cloud-Ressourcenverbindung zu verwenden, wird die Funktion in einer Umgebung ausgeführt, in der der Netzwerkzugriff blockiert ist. Wenn Ihre UDF auf Onlinedienste zugreift, müssen Sie sie mit einer Cloud-Ressourcenverbindung erstellen. Andernfalls wird der Zugriff des UDF auf das Netzwerk blockiert, bis ein internes Verbindungstimeout erreicht wird.
Im folgenden Beispiel wird gezeigt, wie Sie über eine Python-UDF auf den Cloud Translation-Dienst zugreifen. Dieses Beispiel enthält zwei Projekte: ein Projekt mit dem Namen my_query_project
, in dem Sie die UDF und die Cloud-Ressourcenverbindung erstellen, und ein Projekt mit dem Namen my_translate_project
, in dem Sie die Cloud-Übersetzung ausführen.
Cloud-Ressourcen-Verbindung erstellen
Zuerst erstellen Sie in my_query_project
eine Cloud-Ressourcenverbindung. Folgen Sie der Anleitung auf der Seite Cloud-Ressourcen-Verbindung erstellen, um die Cloud-Ressourcen-Verbindung zu erstellen.
Öffnen Sie die Verbindung nach dem Erstellen und kopieren Sie im Bereich Verbindungsinformationen die Dienstkonto-ID. Sie benötigen diese ID, wenn Sie Berechtigungen für die Verbindung konfigurieren. Wenn Sie eine Verbindungsressource erstellen, erstellt BigQuery ein eindeutiges Systemdienstkonto und ordnet es der Verbindung zu.
Zugriff auf das Dienstkonto der Verbindung gewähren
Wenn Sie dem Dienstkonto für die Cloud-Ressourcenverbindung Zugriff auf Ihre Projekte gewähren möchten, weisen Sie ihm in my_query_project
die Rolle Nutzer der Dienstnutzung (roles/serviceusage.serviceUsageConsumer
) und in my_translate_project
die Rolle Cloud Translation API-Nutzer (roles/cloudtranslate.user
) zu.
Rufen Sie die IAM-Seite auf.
Prüfen Sie, ob
my_query_project
ausgewählt ist.Klicken Sie auf
Zugriff gewähren.Geben Sie im Feld Neue Hauptkonten die Dienstkonto-ID der Cloud-Ressourcenverbindung ein, die Sie zuvor kopiert haben.
Wählen Sie im Feld Rolle auswählen die Option Dienstnutzung und dann Nutzer der Dienstnutzung aus.
Klicken Sie auf Speichern.
Wählen Sie in der Projektauswahl
my_translate_project
aus.Rufen Sie die IAM-Seite auf.
Klicken Sie auf
Zugriff gewähren.Geben Sie im Feld Neue Hauptkonten die Dienstkonto-ID der Cloud-Ressourcenverbindung ein, die Sie zuvor kopiert haben.
Wählen Sie im Feld Rolle auswählen die Option Cloud Translation und dann Cloud Translation API-Nutzer aus.
Klicken Sie auf Speichern.
Python-UDF erstellen, das den Cloud Translation-Dienst aufruft
Erstellen Sie in my_query_project
eine Python-UDF, die den Cloud Translation-Dienst über Ihre Cloud-Ressourcenverbindung aufruft.
Rufen Sie die Seite BigQuery auf.
Geben Sie die folgende
CREATE FUNCTION
-Anweisung in den Abfrageeditor ein: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;
Ersetzen Sie Folgendes:
PROJECT_ID.DATASET_ID
: Projekt-ID und Dataset-IDREGION.CONNECTION_ID
: Region und Verbindungs-ID Ihrer Verbindung
Klicken Sie auf
Ausführen.Die Ausgabe sollte so aussehen:
+--------------------------+-------------------------------+ | text | translated_text | +--------------------------+-------------------------------+ | Hello | Hola | | Good morning | Buen dia | | Goodbye | Adios | +--------------------------+-------------------------------+
Unterstützte Standorte
Python-UDFs werden an allen multiregionalen und regionalen Standorten in BigQuery unterstützt.
Preise
Python-UDFs werden ohne Aufpreis angeboten.
Wenn die Abrechnung aktiviert ist, gilt Folgendes:
- Die Kosten für Python-UDFs werden über die SKU für BigQuery-Dienste abgerechnet.
- Die Gebühren sind proportional zur Rechenleistung und zum Arbeitsspeicherverbrauch, die beim Aufrufen der Python-UDF verbraucht werden.
- Kunden von Python-UDFs werden auch die Kosten für das Erstellen oder Neuerstellen des UDF-Container-Images in Rechnung gestellt. Diese Gebühr ist proportional zu den Ressourcen, die zum Erstellen des Images mit Kundencode und Abhängigkeiten verwendet wurden.
- Wenn Python-UDFs zu ausgehendem Traffic in externen Netzwerken oder im Internet führen, werden Ihnen auch Kosten für ausgehenden Internettraffic der Premium-Stufe von Cloud Networking in Rechnung gestellt.