Création d’UDFs Python

Cette rubrique montre comment créer et installer une UDF Python (fonction définie par l’utilisateur).

Dans ce chapitre :

Écrire le code Python

Écriture le module et la fonction Python

Écrivez un module qui suit les spécifications ci-dessous :

  • Définissez le module. Un module est un fichier contenant des définitions et des instructions Python.

  • Définissez une fonction à l’intérieur du module.

  • Si la méthode accepte des arguments, chaque argument doit être l’un des types de données spécifiés dans la colonne Python Data Type de la table SQL-Python Type Mappings.

    Les arguments de fonction sont liés par leur position, et non par leur nom. Le premier argument transmis à l’UDF est le premier argument reçu par la méthode Python.

  • Spécifiez une valeur de retour appropriée. Comme une UDF Python doit être une fonction scalaire, elle doit renvoyer une valeur à chaque fois qu’elle est appelée. Le type de la valeur de retour doit être l’un des types de données spécifiés dans la colonne Python Data Type de la table SQL-Python Type Mappings. Le type de la valeur de retour doit être compatible avec le type de données SQL spécifié dans la clause RETURNS de l’instruction CREATE FUNCTION.

  • Votre module peut contenir plus d’une fonction. La fonction qui est appelée par Snowflake peut appeler d’autres fonctions dans le même module ou dans d’autres modules.

  • Votre fonction (et toute fonction appelée par votre fonction) doit respecter les contraintes Snowflake imposées pour les UDFs Python.

Note

Les UDFs Python vectorisées vous permettent de définir des fonctions Python qui reçoivent des lots de lignes d’entrée sous forme de DataFrames Pandas et renvoient des lots de résultats sous forme de tableaux ou de séries Pandas. Pour plus d’informations, voir UDFs Python vectorisées.

Création de la fonction dans Snowflake

Vous devez exécuter une instruction CREATE FUNCTION pour spécifier :

  • Nom à utiliser pour l’UDF.

  • Le nom de la fonction Python à appeler lorsque l’UDF Python est appelée.

Le nom de l’UDF ne doit pas nécessairement correspondre au nom de la fonction du gestionnaire écrit en Python. La clause HANDLER dans l’instruction CREATE FUNCTION associe le nom de l’UDF à la fonction Python.

Pour choisir un nom pour l’UDF, reportez-vous à Nommage et surcharge de procédures et d’UDFs :

Dans le corps de l’instruction CREATE FUNCTION, les arguments de la fonction sont liés à la position, pas au nom. Le premier argument déclaré dans l’instruction CREATE FUNCTION est le premier argument transmis à la fonction Python.

Pour plus d’informations sur les types de données des arguments, voir Mappages des types de données SQL-Python.

Définissez runtime_version sur la version de l’environnement d’exécution Python requise par votre code. Les versions de Python prises en charge sont les suivantes :

  • 3,8

  • 3,9

  • 3,10

  • 3,11

UDFs avec du code en ligne vs. UDFs avec du code téléchargé à partir d’une zone de préparation

Le code d’une UDF Python peut être spécifié de l’une des manières suivantes :

  • Téléchargé à partir d’une zone de préparation : l’instruction CREATE FUNCTION spécifie l’emplacement d’un code source Python existant dans une zone de préparation.

  • En ligne : l’instruction CREATE FUNCTION spécifie le code source Python.

Création d’une UDF Python en ligne

Pour une UDF en ligne, vous fournissez le code source Python dans le cadre de l’instruction CREATE FUNCTION.

Par exemple, l’instruction suivante crée une UDF Python en ligne qui ajoute +1 à un nombre entier donné :

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

Le code source Python est spécifié dans la clause AS. Le code source peut être délimité soit de guillemets simples, soit d’une paire de signes de dollar ($$). L’utilisation du double signe dollar est généralement plus facile si le code source contient des guillemets simples intégrés.

Appelez l’UDF :

select addone(10);
Copy

Voici la sortie :

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

Le code source Python peut contenir plus d’un module, et plus d’une fonction dans un module, donc la clause HANDLER spécifie le module et la fonction à appeler.

Une UDF Python en ligne peut appeler du code dans les modules qui sont inclus dans la clause IMPORTS.

Pour plus de détails sur la syntaxe de l’instruction CREATE FUNCTION, voir CREATE FUNCTION.

Pour plus d’exemples, voir Exemples d’UDF Python en ligne.

Création d’une UDF Python avec du code téléchargé à partir d’une zone de préparation

Les instructions suivantes créent une simple UDF Python en utilisant du code téléchargé à partir d’une zone de préparation. La zone de préparation hébergeant le fichier doit être lisible par le propriétaire de l’UDF. En outre, les fichiers ZIP doivent être autonomes et ne pas dépendre de scripts d’installation supplémentaires pour être exécutés.

Créez un fichier Python nommé sleepy.py qui contient votre code source :

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

Lancez SnowSQL (CLI client) et utilisez la commande PUT pour copier le fichier du système de fichiers local vers une zone de préparation utilisateur par défaut, nommée @~. (La commande PUT ne peut pas être exécutée par la GUI Snowflake.)

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

Si vous supprimez ou renommez le fichier, vous ne pouvez plus appeler l’UDF. Si vous devez mettre à jour votre fichier, faites-le pendant qu’aucun appel à l’UDF ne soit possible. Si l’ancien fichier .jar se trouve toujours dans la zone de préparation, la commande PUT doit inclure la clause OVERWRITE=TRUE.

Créez l’UDF. Le gestionnaire spécifie le module et la fonction.

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

Appelez l’UDF :

select dream(3);

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

Spécification de fichiers d’importation multiples

Voici un exemple de la façon de spécifier plusieurs fichiers d’importation.

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

Note

Les noms des fichiers d’importation spécifiés doivent être différents. Par exemple, ceci ne fonctionnera pas : imports=('@python_udf_dep/bar/python_imports.zip', '@python_udf_dep/foo/python_imports.zip').

Accorder des privilèges sur la fonction

Pour qu’un rôle autre que le propriétaire de la fonction puisse appeler la fonction, le propriétaire doit accorder les privilèges appropriés au rôle.

Les instructions GRANT pour une UDF Python sont essentiellement identiques aux instructions GRANT pour d’autres UDFs, comme les UDFs JavaScript.

Par exemple :

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