Schreiben von gespeicherten Prozeduren in Python

Unter diesem Thema wird erklärt, wie Sie eine gespeicherte Prozedur in Python schreiben. Sie können die Snowpark-Bibliothek innerhalb Ihrer gespeicherten Prozedur verwenden, um Abfragen, Aktualisierungen und andere Arbeiten an Tabellen in Snowflake auszuführen.

Unter diesem Thema:

Einführung

Mit gespeicherten Snowpark-Prozeduren können Sie Ihre Datenpipeline in Snowflake erstellen und ausführen, wobei ein Snowflake-Warehouse als Compute-Framework dient. Erstellen Sie Ihre Datenpipeline, indem Sie die Snowpark-API für Python zum Schreiben gespeicherter Prozeduren verwenden. Um die Ausführung dieser gespeicherten Prozeduren zu planen, verwenden Sie Aufgaben (Tasks).

Weiter Informationen zu Machine Learning-Modellen und zu Snowpark Python finden Sie unter Training von Machine Learning-Modellen mit Snowpark Python.

Sie können gespeicherte Snowpark-Prozeduren für Python unter Verwendung eines Python-Arbeitsblatts oder unter Verwendung einer lokalen Entwicklungsumgebung schreiben.

Sie können während der Ausführung Ihres Handler-Codes Protokoll- und Ablaufverfolgungsdaten erfassen. Weitere Informationen dazu finden Sie unter Übersicht zu Protokollierung und Ablaufverfolgung.

Bemerkung

Um eine anonyme Prozedur sowohl zu erstellen als auch aufzurufen, verwenden Sie CALL (mit anonymen Prozeduren). Das Erstellen und Aufrufen einer anonymen Prozedur erfordert keine Rolle mit CREATE PROCEDURE-Schemaberechtigungen.

Voraussetzungen für das lokale Schreiben von gespeicherten Prozeduren

Um gespeicherte Python-Prozeduren in Ihrer lokalen Entwicklungsumgebung schreiben zu können, müssen folgende Voraussetzungen erfüllt sein:

  • Sie müssen Version 0.4.0 oder eine neuere Version der Snowpark-Bibliothek verwenden.

  • Aktivieren Sie Anaconda-Pakete, damit Snowpark Python die erforderlichen Abhängigkeiten von Drittanbietern laden kann. Weitere Informationen dazu finden Sie unter Verwenden von Drittanbieterpaketen aus Anaconda.

  • Folgende Versionen von Python werden unterstützt:

    • 3.8

    • 3.9

    • 3.10

    • 3.11

Stellen Sie sicher, dass Ihre Entwicklungsumgebung für die Verwendung der Snowpark-Bibliothek eingerichtet ist. Weitere Informationen dazu finden Sie unter Einrichten Ihrer Entwicklungsumgebung für Snowpark.

Schreiben des Python-Codes für die gespeicherte Prozedur

Für die Logik der Prozedur schreiben Sie Handler-Code, der bei Aufruf der Prozedur ausgeführt wird. In diesem Abschnitt wird das Design eines Handlers beschrieben.

Zum Erstellen einer gespeicherten Prozedur aus dem Handler-Code gibt es verschiedenen Möglichkeiten:

Einschränkungen

In dieser Vorschau bestehen für gespeicherte Snowpark-Prozeduren die folgenden Einschränkungen:

  • Das Erstellen von Prozessen wird in gespeicherten Prozeduren nicht unterstützt.

  • Das Ausführen paralleler Abfragen wird in gespeicherten Prozeduren nicht unterstützt.

  • Sie können keine APIs verwenden, die PUT/GET-Befehle ausführen, einschließlich Session.sql("PUT ...") und Session.sql("GET ...").

  • Beim Herunterladen von Dateien aus einem Stagingbereich mit session.file.get wird die Mustererkennung nicht unterstützt.

  • Wenn Sie Ihre gespeicherte Prozedur über eine Aufgabe ausführen, müssen Sie beim Erstellen der Aufgabe ein Warehouse angeben. Sie können zum Ausführen der Aufgabe keine von Snowflake verwalteten Computeressourcen verwenden.

  • Das Erstellen benannter temporärer Objekte wird in einer gespeicherten Prozedur mit Eigentümerrechten nicht unterstützt. Eine gespeicherte Prozedur mit Eigentümerrechten ist eine gespeicherte Prozedur, die mit den Berechtigungen des Eigentümers der gespeicherten Prozedur ausgeführt wird. Weitere Informationen dazu finden Sie unter Aufruferrechte oder Eigentümerrechte.

Planen des Schreibens Ihrer gespeicherten Prozedur

Gespeicherte Prozeduren werden innerhalb von Snowflake ausgeführt. Daher müssen Sie den Code, den Sie schreiben, unter Berücksichtigung dieser Tatsache planen.

  • Begrenzen Sie den Verbrauch von Arbeitsspeicher. Snowflake belegt Methoden mit einer Begrenzung hinsichtlich der benötigten Menge an Arbeitsspeicher. Weitere Hinweise dazu finden Sie unter Entwerfen von Handlern unter Berücksichtigung der Snowflake-bedingten Einschränkungen.

  • Stellen Sie sicher, dass Ihre Handler-Methode oder Funktion threadsicher ist.

  • Befolgen Sie die Regeln und Sicherheitsbeschränkungen. Weitere Informationen dazu finden Sie unter Sicherheitsverfahren für UDFs und Prozeduren.

  • Entscheiden Sie, ob Sie die gespeicherte Prozedur mit Aufruferrechten oder mit Eigentümerrechten ausführen möchten.

  • Berücksichtigen Sie die „snowflake-snowpark-python“-Version, die zum Ausführen gespeicherter Prozeduren verwendet wird. Aufgrund von Einschränkungen im Freigabeprozess von gespeicherten Prozeduren liegt die Version der „snowflake-snowpark-python“-Bibliothek, die in der Umgebung für die gespeicherte Python-Prozedur verfügbar ist, normalerweise eine Version hinter der öffentlich freigegebenen Version zurück. Verwenden Sie folgende SQL, um die neueste verfügbare Version zu ermitteln:

    select * from information_schema.packages where package_name = 'snowflake-snowpark-python' order by version desc;
    
    Copy

Schreiben der Methode oder Funktion

Beachten Sie beim Schreiben der Methode oder Funktion für die gespeicherte Prozedur Folgendes:

  • Geben Sie das Snowpark-Session-Objekt als erstes Argument Ihrer Methode oder Funktion an. Wenn Sie Ihre gespeicherte Prozedur aufrufen, erstellt Snowflake automatisch ein Session-Objekt und übergibt dieses an Ihre gespeicherte Prozedur. (Sie können das Session-Objekt nicht selbst erstellen.)

  • Für die restlichen Argumente und für den Rückgabewert werden die Python-Typen verwendet, die den Snowflake-Datentypen entsprechen. Snowflake unterstützt die Python-Datentypen, die unter SQL-Python-Zuordnung von Datentypen für Parameter und Rückgabetypen aufgelistet sind.

Fehlerbehandlung

Sie können die üblichen Python-Techniken zur Ausnahmebehandlung verwenden, um Fehler innerhalb der Prozedur abzufangen.

Wenn innerhalb der Methode eine Ausnahme auftritt, die nicht von der Methode abgefangen wird, gibt Snowflake einen Fehler aus, der den Stacktrace für die Ausnahme enthält. Wenn die Protokollierung von unbehandelten Ausnahmen aktiviert ist, protokolliert Snowflake Daten zu unbehandelten Ausnahmen in einer Ereignistabelle.

Abhängigkeiten für Code zur Verfügung stellen

Wenn Ihr Handler-Code von Code abhängt, der außerhalb des Handlers selbst definiert ist (z. B. in einem Modul definierter Code) oder von Ressourcendateien, können Sie diese Abhängigkeiten für Ihren Code zur Verfügung stellen, indem Sie ihn in einen Stagingbereich hochladen. Weitere Informationen dazu finden Sie unter Abhängigkeiten für Code zur Verfügung stellen und für Python-Arbeitsblätter unter Python-Datei aus einem Stagingbereich zu einem Arbeitsblatt hinzufügen.

Wenn Sie Ihre gespeicherte Prozedur mit SQL erstellen, verwenden Sie beim Schreiben der CREATE PROCEDURE-Anweisung die IMPORTS-Klausel, um auf die Abhängigkeitsdateien zu verweisen.

Zugriff auf Daten in Snowflake über Ihre gespeicherte Prozedur

Um auf Daten in Snowflake zuzugreifen, verwenden Sie die Snowpark-Bibliotheks-APIs.

Bei der Verarbeitung eines Aufrufs Ihrer gespeicherten Python-Prozedur erstellt Snowflake ein Snowpark-Session-Objekt und übergibt das Objekt an die Methode oder Funktion für Ihre gespeicherte Prozedur.

Wie bei gespeicherten Prozeduren in anderen Sprachen wird der Kontext für die Sitzung (z. B. die Berechtigungen, die aktuelle Datenbank, das aktuelle Schema usw.) dadurch bestimmt, ob die gespeicherte Prozedur mit Aufruferrechten oder mit Eigentümerrechten ausgeführt wird. Weitere Details dazu finden Sie unter Accessing and Setting the Session State.

Sie können dieses Session-Objekt verwenden, um APIs in der Snowpark-Bibliothek aufzurufen. Sie können zum Beispiel einen DataFrame für eine Tabelle erstellen oder eine SQL-Anweisung ausführen.

Weitere Informationen dazu finden Sie im Snowpark-Entwicklerhandbuch.

Beispiel für Datenzugriff

Es folgt ein Beispiel für eine Python-Methode, die eine bestimmte Anzahl von Zeilen aus einer Tabelle in eine andere Tabelle kopiert. Der Methode werden die folgenden Argumente übergeben:

  • Ein Snowpark-Session-Objekt

  • Der Name der Tabelle, aus der die Zeilen kopiert werden sollen

  • Der Name der Tabelle, in der die Zeilen gespeichert werden sollen

  • Die Anzahl der zu kopierenden Zeilen

Die Methode in diesem Beispiel gibt eine Zeichenfolge zurück. Wenn Sie dieses Beispiel in einem Python-Arbeitsblatt ausführen, ändern Sie den Rückgabetyp des Arbeitsblatts in einen String.

def run(session, from_table, to_table, count):

  session.table(from_table).limit(count).write.save_as_table(to_table)

  return "SUCCESS"
Copy

Lesen von Dateien

Mit der Klasse SnowflakeFile des Snowpark-Moduls snowflake.snowpark.files können Sie dynamisch eine Datei aus einem Stagingbereich mit Ihrem Python-Handler lesen.

Snowflake unterstützt das Lesen von Dateien mit SnowflakeFile sowohl für gespeicherte Prozeduren als auch für benutzerdefinierte Funktionen. Weitere Informationen zum Lesen von Dateien mit Ihrem Handler-Code sowie weitere Beispiele finden Sie unter Lesen einer Datei mit einem Python-UDF-Handler.

Dieses Beispiel zeigt, wie Sie eine gespeicherte Prozedur mit Eigentümerrechten, die eine Datei mit der Klasse SnowflakeFile liest, erstellen und aufrufen.

Erstellen Sie die gespeicherte Prozedur mit einem Inline-Handler, und geben Sie den Eingabemodus als binär an, indem Sie rb als mode-Argument übergeben:

CREATE OR REPLACE PROCEDURE calc_phash(file_path string)
RETURNS STRING
LANGUAGE PYTHON
RUNTIME_VERSION = '3.8'
PACKAGES = ('snowflake-snowpark-python','imagehash','pillow')
HANDLER = 'run'
AS
$$
from PIL import Image
import imagehash
from snowflake.snowpark.files import SnowflakeFile

def run(ignored_session, file_path):
    with SnowflakeFile.open(file_path, 'rb') as f:
        return imagehash.average_hash(Image.open(f))
$$;
Copy

Rufen Sie die gespeicherte Prozedur auf:

CALL calc_phash(build_scoped_file_url(@my_files, 'my_image.jpg'));
Copy

Verwenden von Drittanbieterpaketen aus Anaconda

Sie können beim Erstellen von gespeicherten Prozeduren in Python angeben, dass Anaconda-Pakete installiert werden sollen. Eine Liste der Drittanbieterpakete von Anaconda finden Sie im Anaconda-Snowflake-Kanal. Diese Drittanbieter-Pakete werden von Anaconda erstellt und bereitgestellt. Sie können den Snowflake-Conda-Kanal für lokale Tests und Entwicklung kostenlos auf Grundlage der ergänzenden Bedingungen für eingebettete Software in den Anaconda-Nutzungsbedingungen verwenden.

Informationen zu bestehenden Einschränkungen finden Sie unter Einschränkungen.

Erste Schritte

Bevor Sie die von Anaconda in Snowflake bereitgestellten Pakete verwenden können, müssen Sie die Snowflake-Bedingungen für Drittanbieter anerkennen.

Bemerkung

Sie müssen der Administrator der Organisation sein (Rolle ORGADMIN), um die Bedingungen akzeptieren zu können. Sie müssen die Bedingungen nur einmal für Ihr Snowflake-Konto akzeptieren. Siehe Aktivieren der ORGADMIN-Rolle für ein Konto.

  1. Melden Sie sich bei Snowsight an.

  2. Wählen Sie Admin » Billing & Terms aus.

  3. Wählen Sie im Abschnitt Anaconda die Option Enable aus.

  4. Klicken Sie im Anaconda Packages-Dialog auf den Link, um die Snowflake-Bedingungen für Drittanbieter zu prüfen.

  5. Wenn Sie mit den Bedingungen einverstanden sind, klicken Sie auf Acknowledge & Continue.

Wenn Sie beim Versuch, die Nutzungsbedingungen zu akzeptieren, eine Fehlermeldung erhalten, fehlt in Ihrem Benutzerprofil möglicherweise ein Vorname, ein Nachname oder eine E-Mail-Adresse. Wenn Sie eine Administratorrolle haben, finden Sie unter Benutzerdetails zum Benutzerprofil hinzufügen entsprechende Informationen zum Aktualisieren Ihres Profils in Snowsight. Wenden Sie sich andernfalls an einen Administrator, um Ihr Konto zu aktualisieren.

Bemerkung

Wenn Sie die Snowflake-Bedingungen für Drittanbieter wie oben beschrieben nicht anerkennen, können Sie dennoch gespeicherte Prozeduren verwenden, allerdings mit folgenden Einschränkungen:

  • Sie können keine Pakete von Drittanbietern aus Anaconda verwenden.

  • Sie können Snowpark Python weiterhin als Paket in einer gespeicherten Prozedur angeben, aber Sie können keine bestimmte Version angeben.

  • Sie können die to_pandas-Methode nicht zum Interagieren mit einem DataFrame-Objekt verwenden.

Anzeigen und Verwenden von Paketen

Sie können alle verfügbaren Pakete und deren Versionsinformationen anzeigen, indem Sie die Information Schema-Ansicht PACKAGES abfragen:

select * from information_schema.packages where language = 'python';
Copy

Weitere Informationen dazu finden Sie in der Snowflake-Dokumentation zu Python-UDFs unter Verwenden von Drittanbieterpaketen.

Erstellen der gespeicherten Prozedur

Sie können eine gespeicherte Prozedur über ein Python-Arbeitsblatt oder mit SQL erstellen.

Erstellen einer gespeicherten Python-Prozedur zum Automatisieren Ihres Python-Arbeitsblattcodes

Erstellen Sie eine gespeicherte Python-Prozedur über ein Python-Arbeitsblatt, um Ihren Code zu automatisieren. Weitere Informationen zum Schreiben von Python-Arbeitsblättern finden Sie unter Schreiben von Snowpark-Code in Python-Arbeitsblättern.

Voraussetzungen

Ihre Rolle muss über OWNERSHIP- oder CREATE PROCEDURE-Berechtigungen für das Datenbankschema verfügen, in dem Sie Ihr Python-Arbeitsblatt für das Bereitstellen als gespeicherte Prozedur ausführen.

Python-Arbeitsblatt als gespeicherte Prozedur bereitstellen

Gehen Sie wie folgt vor, um eine gespeicherte Python-Prozedur zum Automatisieren des Codes in Ihrem Python-Arbeitsblatt zu erstellen:

  1. Melden Sie sich bei Snowsight an.

  2. Öffnen Sie Worksheets.

  3. Öffnen Sie das Python-Arbeitsblatt, das Sie als gespeicherte Prozedur bereitstellen möchten.

  4. Wählen Sie Deploy aus.

  5. Geben Sie einen Namen für die gespeicherte Prozedur ein.

  6. (Optional) Geben Sie einen Kommentar mit Details zur gespeicherten Prozedur ein.

  7. (Optional) Wählen Sie Replace if exists aus, um eine vorhandene gespeicherte Prozedur mit demselben Namen zu ersetzen.

  8. Wählen Sie für Handler die Handler-Funktion für Ihre gespeicherte Prozedur. Beispiel: main.

  9. Überprüfen Sie die von Ihrer Handler-Funktion verwendeten Argumente und überschreiben Sie bei Bedarf die SQL-Datentypzuordnung für ein typisiertes Argument. Einzelheiten über die Zuordnung von Python-Typen zu SQL-Typen finden Sie unter Zuordnung von Datentypen zwischen SQL und Python.

  10. (Optional) Wählen Sie Open in Worksheets aus, um die Definition der gespeicherten Prozedur in einem SQL-Arbeitsblatt zu öffnen.

  11. Wählen Sie Deploy aus, um die gespeicherte Prozedur zu erstellen:

  12. Nachdem die gespeicherte Prozedur erstellt wurde, können Sie zu den Prozedurdetails wechseln oder Done auswählen.

Sie können aus einem Python-Arbeitsblatt mehrere gespeicherte Prozeduren erstellen.

Nachdem Sie eine gespeicherte Prozedur erstellt haben, können Sie diese als Teil einer Aufgabe automatisieren. Weitere Informationen dazu finden Sie unter Ausführen von SQL-Anweisungen für einen Zeitplan mithilfe von Aufgaben.

Zurückgeben von tabellarischen Daten

Sie können eine Prozedur schreiben, die Daten in tabellarischer Form zurückgibt. Gehen Sie wie folgt vor, um eine Prozedur zu schreiben, die Tabellendaten zurückgibt:

  • Geben Sie in der CREATE PROCEDURE-Anweisung TABLE(...) als Rückgabetyp der Prozedur an.

    Als TABLE-Parameter können Sie die Spaltennamen und Typen der zurückgegebenen Daten angeben, sofern Sie diese kennen. Wenn Sie beim Definieren der Prozedur die zurückgegebenen Spalten nicht kennen – z. B. wenn diese zur Laufzeit angegeben werden – können Sie die TABLE-Parameter weglassen. Wenn Sie dies tun, werden die Spalten des Rückgabewerts der Prozedur aus den Spalten des DataFrame konvertiert, der vom Handler zurückgegeben wird. Spaltendatentypen werden gemäß der unter Zuordnung von Datentypen zwischen SQL und Python angegebenen Zuordnung in SQL konvertiert.

  • Schreiben Sie den Handler so, dass er das tabellarische Ergebnis in einem Snowpark-DataFrame zurückgibt.

    Weitere Informationen zu Datenframes finden Sie unter Verwenden von DataFrames in Snowpark Python.

Beispiel

Die Beispiele in diesem Abschnitt veranschaulichen die Rückgabe von Tabellenwerten aus einer Prozedur, die Zeilen herausfiltert, in denen eine Spalte mit einer Zeichenfolge übereinstimmt.

Definieren der Daten

Der Code im folgenden Beispiel erstellt eine Tabelle der Mitarbeiter.

CREATE OR REPLACE TABLE employees(id NUMBER, name VARCHAR, role VARCHAR);
INSERT INTO employees (id, name, role) VALUES (1, 'Alice', 'op'), (2, 'Bob', 'dev'), (3, 'Cindy', 'dev');
Copy

Angeben von Namen und Typen der Rückgabespalten

In diesem Beispiel werden Spaltennamen und -typen in der RETURNS TABLE()-Anweisung angegeben.

CREATE OR REPLACE PROCEDURE filterByRole(tableName VARCHAR, role VARCHAR)
RETURNS TABLE(id NUMBER, name VARCHAR, role VARCHAR)
LANGUAGE PYTHON
RUNTIME_VERSION = '3.8'
PACKAGES = ('snowflake-snowpark-python')
HANDLER = 'filter_by_role'
AS
$$
from snowflake.snowpark.functions import col

def filter_by_role(session, table_name, role):
   df = session.table(table_name)
   return df.filter(col("role") == role)
$$;
Copy

Weglassen von Namen und Typen der Rückgabespalten

Der Code im folgenden Beispiel deklariert eine Prozedur, mit der Spaltennamen und -typen des Rückgabewerts aus den im Rückgabewert des Handlers enthaltenen Spalten extrapoliert werden können. Die Spaltennamen und -typen aus der RETURNS TABLE()-Anweisung werden weggelassen.

CREATE OR REPLACE PROCEDURE filterByRole(tableName VARCHAR, role VARCHAR)
RETURNS TABLE()
LANGUAGE PYTHON
RUNTIME_VERSION = '3.8'
PACKAGES = ('snowflake-snowpark-python')
HANDLER = 'filter_by_role'
AS
$$
from snowflake.snowpark.functions import col

def filter_by_role(session, table_name, role):
  df = session.table(table_name)
  return df.filter(col("role") == role)
$$;
Copy

Aufrufen der Prozedur

Im folgenden Beispiel wird die gespeicherte Prozedur aufgerufen:

CALL filterByRole('employees', 'dev');
Copy

Der Prozeduraufruf erzeugt die folgende Ausgabe:

+----+-------+------+
| ID | NAME  | ROLE |
+----+-------+------+
| 2  | Bob   | dev  |
| 3  | Cindy | dev  |
+----+-------+------+

Aufrufen Ihrer gespeicherten Prozedur

Nachdem Sie eine gespeicherte Prozedur erstellt haben, können Sie diese mit SQL oder als Teil einer geplanten Aufgabe aufrufen.

Beispiele

Ausführen von gleichzeitigen Aufgaben mit Worker-Prozessen

Sie können gleichzeitige Aufgaben mithilfe von Python-Worker-Prozessen ausführen. Dies kann nützlich sein, wenn Sie parallele Aufgaben ausführen müssen, die die Vorteile mehrerer CPU-Kerne auf den Warehouse-Knoten ausnutzen.

Bemerkung

Snowflake empfiehlt, das integrierte Python-Multiprocessing-Modul nicht zu verwenden.

Um Fälle zu umgehen, in denen die Python Global Interpreter Lock verhindert, dass ein Multitasking-Ansatz über alle CPU-Kerne skaliert, können Sie gleichzeitige Aufgaben über separate Worker-Prozesse statt über Threads ausführen.

Sie können dies bei Snowflake-Warehouses tun, indem Sie die Klasse Parallel der Bibliothek joblib verwenden, wie in dem folgenden Beispiel.

CREATE OR REPLACE PROCEDURE joblib_multiprocessing_proc(i INT)
  RETURNS STRING
  LANGUAGE PYTHON
  RUNTIME_VERSION = 3.8
  HANDLER = 'joblib_multiprocessing'
  PACKAGES = ('snowflake-snowpark-python', 'joblib')
AS $$
import joblib
from math import sqrt

def joblib_multiprocessing(session, i):
  result = joblib.Parallel(n_jobs=-1)(joblib.delayed(sqrt)(i ** 2) for i in range(10))
  return str(result)
$$;
Copy

Bemerkung

Das für joblib.Parallel verwendete Standard-Backend unterscheidet zwischen Standard- und Snowpark-optimierten Snowflake-Warehouses.

  • Standardeinstellung für Standard-Warehouses: threading

  • Standardeinstellung für Snowpark-optimierte Warehouses: loky (Multiprocessing)

Sie können die Standardeinstellung des Backends außer Kraft setzen, indem Sie die Funktion joblib.parallel_backend aufrufen, wie im folgenden Beispiel.

import joblib
joblib.parallel_backend('loky')
Copy