Erstellen von Python-UDFs

Unter diesem Thema wird das Erstellen und Installieren einer Python-UDF (benutzerdefinierte Funktion) erklärt.

Unter diesem Thema:

Schreiben von Python-Code

Schreiben von Python-Modulen und -Funktionen

Schreiben Sie ein Modul, die den unten stehenden Spezifikationen entspricht:

  • Definieren Sie das Modul. Ein Modul ist eine Datei, die Python-Definitionen und -Anweisungen enthält.

  • Definieren Sie innerhalb des Moduls eine Funktion.

  • Wenn die Funktion Argumente akzeptiert, muss jedes Argument einen Datentyp aufweisen, der in der Spalte Python Data Type der SQL-Python-Typzuordnungstabelle angegeben ist.

    Funktionsargumente werden über die Position gebunden, nicht über den Namen. Das erste Argument, das an die UDF übergeben wird, ist das erste Argument, das von der Python-Funktion empfangen wird.

  • Geben Sie einen geeigneten Rückgabewert an. Da eine Python-UDF eine skalare Funktion sein muss, muss sie bei jedem Aufruf einen Wert zurückgeben. Der Rückgabewert muss einen Datentyp aufweisen, der in der Spalte Python Data Type der SQL-Python-Typzuordnungstabelle angegebenen ist. Der Typ des Rückgabewerts muss mit dem SQL-Datentyp kompatibel sein, der in der RETURNS-Klausel der CREATE FUNCTION-Anweisung angegeben ist.

  • Ihr Modul kann mehr als eine Funktion enthalten. Die Funktion, die von Snowflake aufgerufen wird, kann andere Funktionen im selben Modul oder in anderen Modulen aufrufen.

  • Ihre Funktion (und alle Funktionen, die von Ihrer Funktion aufgerufen werden) muss die Snowflake-Einschränkungen für Python-UDFs einhalten.

Bemerkung

Mit vektorisierten Python-UDFs können Sie Python-Funktionen definieren, mit denen Batches von Eingabezeilen als Pandas DataFrames empfangen und Batches von Ergebnissen als Pandas-Arrays oder Pandas Series zurückgeben werden. Weitere Informationen dazu finden Sie unter Vektorisierte Python-UDFs.

Erstellen der Funktion in Snowflake

Sie müssen eine CREATE FUNCTION-Anweisung ausführen, um Folgendes anzugeben:

  • Der Name, der für die UDF verwendet werden soll.

  • Name der Python-Methode, die aufgerufen werden soll, wenn die Python-UDF aufgerufen wird.

Der Name der UDF muss nicht mit dem Namen der in Python geschriebenen Handler-Funktion übereinstimmen. Die HANDLER-Klausel in der CREATE FUNCTION-Anweisung verknüpft den UDF-Namen mit der Python-Funktion.

Was bei der Wahl des UDF-Namens beachtet werden muss, finden Sie unter Benennen und Überladen von Prozeduren und UDFs.

Innerhalb des Textkörpers (body) der CREATE FUNCTION-Anweisung werden Funktionsargumente über die Position gebunden, nicht über den Namen. Das erste in der CREATE FUNCTION-Anweisung deklarierte Argument ist das erste Argument, das an die Python-Funktion übergeben wird.

Weitere Informationen zu den Datentypen von Argumenten finden Sie unter Zuordnung von Datentypen zwischen SQL und Python.

Setzen Sie runtime_version auf die Version der Python-Laufzeitumgebung, die von Ihrem Code benötigt wird. Folgende Versionen von Python werden unterstützt:

  • 3.8

  • 3.9

  • 3.10

  • 3.11

UDFs mit Inline-Code vs. UDFs mit aus einem Stagingbereich hochgeladenem Code

Der Code für eine Python-UDF kann auf eine der folgenden Arten angegeben werden:

  • Hochgeladen aus einem Stagingbereich: Die CREATE FUNCTION-Anweisung gibt den Speicherort des Stagingbereichs an, in dem sich der Python-Quellcode befindet.

  • Inline: Die CREATE FUNCTION-Anweisung gibt den Python-Quellcode an.

Erstellen einer Inline-Python-UDF

Bei einer Inline-UDF stellen Sie den Python-Quellcode als Teil der CREATE FUNCTION -Anweisung bereit.

Die folgende Anweisung erstellt zum Beispiel eine Inline-Python-UDF, die zu einer gegebenen ganzen Zahl den Wert 1 addiert:

create or replace function addone(i int)
returns int
language python
runtime_version = '3.8'
handler = 'addone_py'
as
$$
def addone_py(i):
  return i+1
$$;
Copy

Der Python-Quellcode wird in der AS-Klausel angegeben. Der Quellcode kann entweder in einfache Anführungszeichen oder in doppelte Dollarzeichen ($$) eingeschlossen sein. Die Verwendung der doppelten Dollarzeichen ist normalerweise einfacher, wenn der Quellcode eingebettete einfache Anführungszeichen enthält.

Aufrufen der UDF:

select addone(10);
Copy

Und hier ist die Ausgabe:

+------------+
| ADDONE(10) |
|------------|
|         11 |
+------------+
Copy

Der Python-Quellcode kann mehr als ein Modul und mehr als eine Funktion in einem Modul enthalten. Daher werden Modul und Funktion für den Aufruf in der HANDLER-Klausel angegeben.

Eine Inline-Python-UDF kann Code in Modulen aufrufen, die in der IMPORTS-Klausel enthalten sind.

Weitere Informationen zur CREATE FUNCTION-Anweisung finden Sie unter CREATE FUNCTION.

Weitere Beispiele finden Sie unter Beispiele für Inline-Python-UDFs.

Erstellen eines Python-UDF mit aus einem Stagingbereich hochgeladenem Code

Mit den folgenden Anweisungen wird eine einfache Python-UDF erstellt, deren Code aus einem Stagingbereich hochgeladen wird. Der Stagingbereich, der die Datei hostet, muss für den Eigentümer der UDF-Datei lesbar sein. Außerdem müssen ZIP-Dateien eigenständig sein und dürfen keine zusätzlichen Setup-Skripte zur Ausführung benötigen.

Erstellen Sie eine Python-Datei mit dem Namen sleepy.py, die Ihren Quellcode enthält:

def snore(n):   # return a series of n snores
    result = []
    for a in range(n):
        result.append("Zzz")
    return result
Copy

Starten Sie SnowSQL (CLI-Client), und verwenden Sie den PUT-Befehl, um die Datei aus dem lokalen Dateisystem in den Stagingbereich @~ des Standardbenutzers zu kopieren. (Beachten Sie, dass der PUT-Befehl nicht über die Snowflake-GUI ausgeführt werden kann.)

put
file:///Users/Me/sleepy.py
@~/
auto_compress = false
overwrite = true
;
Copy

Wenn Sie die Datei löschen oder umbenennen, können Sie die UDF-Datei nicht mehr aufrufen. Wenn Sie Ihre Datei aktualisieren müssen, dann nehmen Sie die Aktualisierung vor, während keine Aufrufe an die UDF erfolgen können. Wenn sich die alte Datei noch im Stagingbereich befindet, muss der PUT-Befehl die OVERWRITE=TRUE-Klausel enthalten.

Erstellen Sie die UDF. Der Handler gibt das Modul und die Funktion an.

create or replace function dream(i int)
returns variant
language python
runtime_version = '3.8'
handler = 'sleepy.snore'
imports = ('@~/sleepy.py')
Copy

Aufrufen der UDF:

select dream(3);

+----------+
| DREAM(3) |
|----------|
| [        |
|   "Zzz", |
|   "Zzz", |
|   "Zzz"  |
| ]        |
+----------+
Copy

Angeben mehrerer Importdateien

Das folgende Beispiel zeigt, wie Sie mehrere Importdateien angeben können.

create or replace function multiple_import_files(s string)
returns string
language python
runtime_version=3.8
imports=('@python_udf_dep/bar/python_imports_a.zip', '@python_udf_dep/foo/python_imports_b.zip')
handler='compute'
as
$$
def compute(s):
  return s
$$;
Copy

Bemerkung

Die angegebenen Importdateinamen müssen unterschiedlich sein. Beispielsweise funktioniert Folgendes nicht: imports=('@python_udf_dep/bar/python_imports.zip', '@python_udf_dep/foo/python_imports.zip').

Erteilen von Berechtigungen für die Funktion

Damit eine andere Rolle als der Funktionseigentümer die Funktion aufrufen kann, muss der Eigentümer der Rolle entsprechende Berechtigungen erteilen.

Die GRANT-Anweisungen für ein Python-UDF sind im Wesentlichen identisch mit den GRANT-Anweisungen für andere UDFs, wie zum Beispiel JavaScript-UDFs.

Beispiel:

GRANT USAGE ON FUNCTION my_python_udf(number, number) TO my_role;
Copy