Exemples de gestionnaires d’UDF Python¶

Cette rubrique comprend des exemples simples de code de gestionnaire d’UDF Ă©crits en Python.

Pour obtenir des informations sur l’utilisation de Python pour crĂ©er un gestionnaire d’UDF, reportez-vous Ă  CrĂ©ation d’UDFs 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,9

  • 3,10

  • 3,11

  • 3,12

Importation d’un paquet dans un gestionnaire en ligne¶

Une sĂ©lection de paquets tiers d’Anaconda est disponible. Pour plus d’informations, voir Utilisation de paquets tiers.

Note

Avant que vous puissiez utiliser les paquets fournis par Anaconda, l’administrateur de votre organisation Snowflake doit accepter les conditions de tiers externes de Snowflake. Pour plus d’informations, voir Utilisation de paquets tiers à partir d’Anaconda.

Le code suivant montre comment importer des paquets et renvoyer leurs versions.

CrĂ©ez l’UDF :

CREATE OR REPLACE FUNCTION py_udf()
  RETURNS VARIANT
  LANGUAGE PYTHON
  RUNTIME_VERSION = 3.9
  PACKAGES = ('numpy','pandas','xgboost==1.5.0')
  HANDLER = 'udf'
AS $$
import numpy as np
import pandas as pd
import xgboost as xgb
def udf():
  return [np.__version__, pd.__version__, xgb.__version__]
$$;
Copy

Appelez l’UDF :

SELECT py_udf();
Copy
+-------------+
| PY_UDF()    |
|-------------|
| [           |
|   "1.19.2", |
|   "1.4.0",  |
|   "1.5.0"   |
| ]           |
+-------------+

Vous pouvez utiliser le mot-clĂ© PACKAGES pour spĂ©cifier les versions des paquets comme suit :

  • Sans version (par exemple numpy)

  • Avec une version exacte (par exemple, numpy==1.25.2)

  • Contrainte Ă  un prĂ©fixe de version en utilisant des caractĂšres gĂ©nĂ©riques (par exemple numpy==1.*)

  • Contrainte Ă  une plage de versions (par exemple numpy>=1.25)

  • Contrainte par plusieurs spĂ©cificateurs de version (par exemple numpy>=1.25,<2) de sorte qu’un paquet qui satisfait Ă  tous les spĂ©cificateurs de version sera sĂ©lectionnĂ©.

Note

L’utilisation de plusieurs opĂ©rateurs de plage (par exemple numpy>=1.25,<2) n’est pas prise en charge dans les politiques de paquets, mais vous pouvez les utiliser lors de la crĂ©ation d’UDF, d’UDTF et de procĂ©dures stockĂ©es Python.

Voici un exemple d’utilisation du caractĂšre gĂ©nĂ©rique * pour contraindre un paquet Ă  un prĂ©fixe de version.

CREATE OR REPLACE FUNCTION my_udf()
  RETURNS STRING
  LANGUAGE PYTHON
  PACKAGES = ('numpy==1.*')
  RUNTIME_VERSION = 3.10
  HANDLER = 'echo'
AS $$
def echo():
  return 'hi'
$$;
Copy

Cet exemple montre comment contraindre un paquet Ă  ĂȘtre supĂ©rieur ou Ă©gal Ă  une version spĂ©cifiĂ©e.

CREATE OR REPLACE FUNCTION my_udf()
  RETURNS STRING
  LANGUAGE PYTHON
  PACKAGES = ('numpy>=1.2')
  RUNTIME_VERSION = 3.10
  HANDLER = 'echo'
AS $$
def echo():
  return 'hi'
$$;
Copy

Cet exemple montre comment utiliser plusieurs spĂ©cificateurs de versions de paquets :

CREATE OR REPLACE FUNCTION my_udf()
  RETURNS STRING
  LANGUAGE PYTHON
  PACKAGES = ('numpy>=1.2,<2')
  RUNTIME_VERSION = 3.10
  HANDLER = 'echo'
AS $$
def echo():
  return 'hi'
$$;
Copy

Lecture d’un fichier¶

Vous pouvez lire le contenu d’un fichier avec le code du gestionnaire d’UDF Python. Par exemple, vous pourriez vouloir lire un fichier pour traiter des donnĂ©es non structurĂ©es.

Pour lire le contenu d’un fichier, vous pouvez :

Lecture d’un fichier spĂ©cifiĂ© de façon statique Ă  l’aide de IMPORTS¶

Vous pouvez lire un fichier en spécifiant le nom du fichier et le nom de la zone de préparation dans la clause IMPORTS de la commande CREATE FUNCTION.

Lorsque vous spĂ©cifiez un fichier dans la clause IMPORTS, Snowflake copie ce fichier de la zone de prĂ©paration vers le rĂ©pertoire personnel (Ă©galement appelĂ© rĂ©pertoire d’importation) de l’UDF, qui est le rĂ©pertoire Ă  partir duquel l’UDF lit le fichier.

Snowflake copie les fichiers importĂ©s dans un rĂ©pertoire unique. Tous les fichiers de ce rĂ©pertoire doivent avoir des noms uniques, de sorte que chaque fichier de votre clause IMPORTS doit avoir un nom distinct. Cette rĂšgle s’applique mĂȘme si les fichiers commencent dans diffĂ©rentes zones de prĂ©paration ou diffĂ©rents sous-rĂ©pertoires au sein d’une zone de prĂ©paration.

Note

Vous ne pouvez importer des fichiers qu’à partir du rĂ©pertoire de premier niveau d’une zone de prĂ©paration, pas des sous-dossiers.

L’exemple suivant utilise un gestionnaire Python en ligne qui lit un fichier appelĂ© file.txt Ă  partir d’une zone de prĂ©paration nommĂ©e my_stage. Le gestionnaire rĂ©cupĂšre l’emplacement du rĂ©pertoire personnel de l’UDF en utilisant la mĂ©thode Python sys._xoptions avec l’option systĂšme snowflake_import_directory.

Snowflake lit le fichier une seule fois pendant la crĂ©ation de l’UDF, et ne le relira pas pendant l’exĂ©cution de l’UDF si la lecture du fichier a lieu en dehors du gestionnaire cible.

CrĂ©ez l’UDF avec un gestionnaire en ligne :

CREATE OR REPLACE FUNCTION my_udf()
  RETURNS STRING
  LANGUAGE PYTHON
  RUNTIME_VERSION = 3.9
  IMPORTS = ('@my_stage/file.txt')
  HANDLER = 'compute'
AS $$
import sys
import os

with open(os.path.join(sys._xoptions["snowflake_import_directory"], 'file.txt'), "r") as f:
  s = f.read()

def compute():
  return s
$$;
Copy

Lecture d’un fichier spĂ©cifiĂ© de façon dynamique avec SnowflakeFile¶

Vous pouvez lire un fichier depuis une zone de prĂ©paration en utilisant la classe SnowflakeFile dans le module Snowpark snowflake.snowpark.files. La classe SnowflakeFile offre un accĂšs dynamique aux fichiers, ce qui vous permet de diffuser des fichiers de n’importe quelle taille. L’accĂšs dynamique aux fichiers est Ă©galement utile lorsque vous souhaitez itĂ©rer sur plusieurs fichiers. Par exemple, voir Traitement de plusieurs fichiers.

La classe SnowflakeFile possĂšde une mĂ©thode pour ouvrir un fichier : open. La mĂ©thode open renvoie un objet SnowflakeFile qui Ă©tend les objets de fichier IOBase Python.

L’objet SnowflakeFile prend en charge les mĂ©thodes suivantes : IOBase, BufferedIOBase; et RawIOBase :

  • IOBase.fileno

  • IOBase.isatty

  • IOBase.readable

  • IOBase.readinto

  • IOBase.readline

  • IOBase.readlines

  • IOBase.seek

  • IOBase.seekable

  • IOBase.tell

  • BufferedIOBase.readinto1

  • RawIOBase.read

  • RawIOBase.readall

Pour plus d’informations, voir la documentation Python 3.9 sur IOBase. L’appel Ă  des mĂ©thodes non prises en charge dans un serveur Snowflake, telles que la mĂ©thode fileno, entraĂźnera une erreur.

Note

Par dĂ©faut, l’accĂšs aux fichiers avec SnowflakeFile nĂ©cessite des URLs scopĂ©es afin de rendre votre code rĂ©sistant aux attaques par injection de fichiers. Vous pouvez crĂ©er une URL scopĂ©e en SQL Ă  l’aide de la fonction intĂ©grĂ©e BUILD_SCOPED_FILE_URL. Pour plus d’informations sur les URLs scopĂ©es, voir Types d’URLs disponibles pour accĂ©der aux fichiers. Seuls les utilisateurs ayant accĂšs au fichier peuvent crĂ©er une URL scopĂ©e.

Conditions préalables¶

Avant que votre code de gestionnaire Python puisse lire un fichier sur une zone de prĂ©paration, vous devez effectuer les opĂ©rations suivantes pour mettre le fichier Ă  la disposition du code :

  1. Créez une zone de préparation accessible à votre gestionnaire.

    Vous pouvez utiliser une zone de prĂ©paration externe ou une zone de prĂ©paration interne. Si vous utilisez une zone de prĂ©paration interne, il peut s’agir d’une zone de prĂ©paration utilisateur lorsque vous prĂ©voyez de crĂ©er une procĂ©dure stockĂ©e avec droits de l’appelant. Sinon, vous devez utiliser une zone de prĂ©paration nommĂ©e. Snowflake ne prend actuellement pas en charge l’utilisation d’une zone de prĂ©paration de table pour les dĂ©pendances UDF.

    Pour en savoir plus sur la crĂ©ation d’une zone de prĂ©paration, voir CREATE STAGE. Pour en savoir plus sur le choix d’un type de zone de prĂ©paration interne, voir SĂ©lection d’une zone de prĂ©paration interne pour les fichiers locaux.

    Des privilĂšges adĂ©quats sur la zone de prĂ©paration doivent ĂȘtre attribuĂ©s au rĂŽle suivant, en fonction de votre casse :

    Cas d’utilisation

    RĂŽle

    UDF ou procédure stockée avec droits du propriétaire

    RĂŽle qui possĂšde l’UDF ou la procĂ©dure stockĂ©e en cours d’exĂ©cution.

    ProcĂ©dure stockĂ©e avec droits de l’appelant

    Rîle de l’utilisateur.

    Pour plus d’informations, voir Accorder des privilĂšges pour les fonctions dĂ©finies par l’utilisateur.

  2. Copiez le fichier que votre code lira dans la zone de préparation.

    Vous pouvez copier le fichier d’un lecteur local vers une zone de prĂ©paration interne en utilisant la commande PUT. Pour des informations sur la mise en zone de prĂ©paration de fichiers avec PUT, voir Mise en zone de prĂ©paration de fichiers de donnĂ©es Ă  partir d’un systĂšme de fichiers local.

    Vous pouvez copier le fichier d’un lecteur local vers une zone de prĂ©paration externe Ă  l’aide de l’un des outils fournis par votre service de stockage dans le Cloud. Pour obtenir de l’aide, consultez la documentation de votre service de stockage dans le Cloud.

Calcul du hachage perceptuel d’une image avec un gestionnaire Python en ligne¶

Cet exemple utilise SnowflakeFile pour lire une paire de fichiers images en zone de préparation et utiliser le hachage perceptuel (pHash) de chaque fichier pour déterminer le degré de similitude des images entre elles.

CrĂ©ez une UDF qui renvoie la valeur phash d’une image, en spĂ©cifiant le mode d’entrĂ©e comme Ă©tant binaire en transmettant rb pour l’argument mode :

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

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

CrĂ©ez une deuxiĂšme UDF qui calcule la distance entre les valeurs de phash de deux images :

CREATE OR REPLACE FUNCTION calc_phash_distance(h1 STRING, h2 STRING)
  RETURNS INT
  LANGUAGE PYTHON
  RUNTIME_VERSION = '3.9'
  PACKAGES = ('imagehash')
  HANDLER = 'run'
AS $$
import imagehash

def run(h1, h2):
  return imagehash.hex_to_hash(h1) - imagehash.hex_to_hash(h2)
$$;
Copy

Mettez en zone de prĂ©paration les fichiers images et actualisez la table du rĂ©pertoire :

PUT file:///tmp/image1.jpg @images AUTO_COMPRESS=FALSE;
PUT file:///tmp/image2.jpg @images AUTO_COMPRESS=FALSE;

ALTER STAGE images REFRESH;
Copy

Appelez l’UDFs :

SELECT
  calc_phash_distance(
    calc_phash(build_scoped_file_url(@images, 'image1.jpg')),
    calc_phash(build_scoped_file_url(@images, 'image2.jpg'))
  ) ;
Copy

Traitement d’un fichier CSV Ă  l’aide d’une UDTF¶

Cet exemple utilise SnowflakeFile pour crĂ©er une UDTF qui extrait le contenu d’un fichier CSV et renvoie les lignes dans un tableau.

CrĂ©ez l’UDTF avec un gestionnaire en ligne :

CREATE FUNCTION parse_csv(file_path STRING)
  RETURNS TABLE (col1 STRING, col2 STRING, col3 STRING)
  LANGUAGE PYTHON
  RUNTIME_VERSION = '3.9'
  PACKAGES = ('snowflake-snowpark-python')
  HANDLER = 'csvparser'
AS $$
from snowflake.snowpark.files import SnowflakeFile

class csvparser:
  def process(self, stagefile):
    with SnowflakeFile.open(stagefile) as f:
      for line in f.readlines():
        lineStr = line.strip()
        row = lineStr.split(",")
        try:
          # Read the columns from the line.
          yield (row[1], row[0], row[2], )
        except:
          pass
$$;
Copy

Mettez en zone de prĂ©paration le fichier CSV et actualisez la table du rĂ©pertoire :

PUT file:///tmp/sample.csv @data_stage AUTO_COMPRESS=FALSE;

ALTER STAGE data_stage REFRESH;
Copy

Appelez l’UDTF en lui transmettant l’URL d’un fichier :

SELECT * FROM TABLE(PARSE_CSV(build_scoped_file_url(@data_stage, 'sample.csv')));
Copy

Traitement de plusieurs fichiers¶

Vous pouvez lire et traiter plusieurs fichiers en transmettant la colonne RELATIVE_PATH d’une table de rĂ©pertoire Ă  votre gestionnaire. Pour plus d’informations sur la colonne RELATIVE_PATH, consultez le rĂ©sultat d’une requĂȘte de table de rĂ©pertoire.

Note

En fonction de la taille de vos fichiers et de vos besoins de calcul, vous pouvez utiliser ALTER WAREHOUSE pour mettre votre entrepĂŽt Ă  une Ă©chelle supĂ©rieure avant d’exĂ©cuter une instruction qui lit et traite plusieurs fichiers.

Appelez l’UDF pour traiter plusieurs fichiers :

L’exemple suivant appelle une UDF au sein d’une instruction CREATE TABLE pour traiter chaque fichier sur une zone de prĂ©paration, puis stocker les rĂ©sultats dans une nouvelle table.

À des fins de dĂ©monstration, l’exemple repose sur les hypothĂšses suivantes :

  • Une zone de prĂ©paration nommĂ©e my_stage contient plusieurs fichiers texte.

  • Il existe une UDF nommĂ©e get_sentiment qui effectue une analyse des sentiments sur du texte non structurĂ©. L’UDF prend en entrĂ©e le chemin d’un fichier texte et renvoie une valeur reprĂ©sentant le sentiment.

CREATE OR REPLACE TABLE sentiment_results AS
SELECT
  relative_path
  , get_sentiment(build_scoped_file_url(@my_stage, relative_path)) AS sentiment
FROM directory(@my_stage);
Copy
Appelez l’UDTF pour traiter plusieurs fichiers :

L’exemple suivant appelle une UDTF nommĂ©e parse_excel_udtf. L’exemple transmet le relative_path de la table du rĂ©pertoire Ă  la zone de prĂ©paration nommĂ©e my_excel_stage.

SELECT t.*
FROM directory(@my_stage) d,
TABLE(parse_excel_udtf(build_scoped_file_url(@my_excel_stage, relative_path)) t;
Copy

Lecture de fichiers avec des URLs et des URIs de zones de préparation¶

L’accĂšs Ă  un fichier avec SnowflakeFile nĂ©cessite par dĂ©faut des URLs scopĂ©es. Cela rend votre code rĂ©sistant aux attaques par injection de fichiers. Toutefois, vous pouvez faire rĂ©fĂ©rence Ă  l’emplacement d’un fichier en utilisant une URI ou une URL de zone de prĂ©paration. Pour ce faire, vous devez appeler la mĂ©thode SnowflakeFile.open avec l’argument mot-clĂ© require_scoped_url = False.

Cette option est utile lorsque vous voulez permettre Ă  un fournisseur de fournir une URI qui n’est accessible qu’au propriĂ©taire de l’UDF. Par exemple, vous pouvez utiliser une URI de zone de prĂ©paration pour l’accĂšs aux fichiers si vous possĂ©dez une UDF et que vous souhaitez lire vos fichiers de configuration ou vos modĂšles de machine learning. Nous ne recommandons pas cette option si vous travaillez avec des fichiers dont les noms sont imprĂ©visibles, tels que les fichiers créés en fonction des entrĂ©es de l’utilisateur.

Cet exemple lit un modĂšle de machine learning dans un fichier et utilise le modĂšle dans une fonction pour effectuer un traitement du langage naturel pour l’analyse des sentiments. L’exemple appelle open avec require_scoped_url = False. Dans les deux formats de localisation des fichiers (URI et URL de zone de prĂ©paration), le propriĂ©taire de l’UDF doit avoir accĂšs au fichier modĂšle.

CrĂ©ez l’UDF avec un gestionnaire en ligne :

CREATE OR REPLACE FUNCTION extract_sentiment(input_data STRING)
  RETURNS STRING
  LANGUAGE PYTHON
  RUNTIME_VERSION = '3.9'
  PACKAGES = ('snowflake-snowpark-python','scikit-learn')
  HANDLER = 'run'
AS $$
from snowflake.snowpark.files import SnowflakeFile
from sklearn.linear_model import SGDClassifier
import pickle

def run(input_data):
  model_file = '@models/NLP_model.pickle'
  # Specify 'mode = rb' to open the file in binary mode.
  with SnowflakeFile.open(model_file, 'rb', require_scoped_url = False) as f:
    model = pickle.load(f)
    return model.predict([input_data])[0]
$$;
Copy

Mettez en zone de prĂ©paration le fichier modĂšle et actualisez la table du rĂ©pertoire :

PUT file:///tmp/NLP_model.pickle @models AUTO_COMPRESS=FALSE;

ALTER STAGE models REFRESH;
Copy

Vous pouvez Ă©galement spĂ©cifier l’UDF avec l’URL de la zone de prĂ©paration du modĂšle pour extraire le sentiment.

Par exemple, crĂ©ez une UDF avec un gestionnaire en ligne qui spĂ©cifie un fichier en utilisant une URL de zone de prĂ©paration :

CREATE OR REPLACE FUNCTION extract_sentiment(input_data STRING)
  RETURNS STRING
  LANGUAGE PYTHON
  RUNTIME_VERSION = '3.9'
  PACKAGES = ('snowflake-snowpark-python','scikit-learn')
  HANDLER = 'run'
AS $$
from snowflake.snowpark.files import SnowflakeFile
from sklearn.linear_model import SGDClassifier
import pickle

def run(input_data):
  model_file = 'https://my_account/api/files/my_db/my_schema/models/NLP_model.pickle'
  # Specify 'rb' to open the file in binary mode.
  with SnowflakeFile.open(model_file, 'rb', require_scoped_url = False) as f:
    model = pickle.load(f)
    return model.predict([input_data])[0]
$$;
Copy

Appelez l’UDF avec les donnĂ©es d’entrĂ©e :

SELECT extract_sentiment('I am writing to express my interest in a recent posting made.');
Copy

Écriture de fichiers¶

Un gestionnaire d’UDF peut Ă©crire des fichiers dans un rĂ©pertoire /tmp créé pour la requĂȘte appelant l’UDF.

N’oubliez pas qu’un rĂ©pertoire /tmp est rĂ©servĂ© Ă  une seule requĂȘte d’appel, alors que plusieurs processus de travail Python peuvent ĂȘtre exĂ©cutĂ©s en mĂȘme temps. Pour Ă©viter les collisions, vous devez vous assurer que l’accĂšs au rĂ©pertoire /tmp est synchronisĂ© avec les autres processus de travail Python ou que les noms des fichiers Ă©crits dans /tmp sont uniques.

Pour un exemple de code, voir DĂ©compression d’un fichier en zone de prĂ©paration dans cette rubrique.

Le code de l’exemple suivant Ă©crit l’entrĂ©e text dans le rĂ©pertoire /tmp. Il ajoute Ă©galement l’ID du processus de la fonction pour garantir l’unicitĂ© de l’emplacement du fichier.

def func(text):
  # Append the function's process ID to ensure the file name's uniqueness.
  file_path = '/tmp/content' + str(os.getpid())
  with open(file_path, "w") as file:
    file.write(text)
Copy

Pour plus d’informations sur l’écriture de fichiers, voir . Écriture de fichiers depuis les UDFs et les UDTFs Snowpark Python.

DĂ©compression d’un fichier en zone de prĂ©paration¶

Vous pouvez stocker un fichier .zip dans une zone de préparation, puis le décompresser dans une UDF en utilisant le module Python zipfile.

Par exemple, vous pouvez tĂ©lĂ©charger un fichier .zip dans une zone de prĂ©paration, puis rĂ©fĂ©rencer le fichier .zip Ă  son emplacement de zone de prĂ©paration dans la clause IMPORTS lorsque vous crĂ©ez l’UDF. Au moment de l’exĂ©cution, Snowflake copiera le fichier en zone de prĂ©paration dans un rĂ©pertoire d’importation Ă  partir duquel votre code pourra y accĂ©der.

Pour plus d’informations sur la lecture et l’écriture de fichiers, voir Lecture d’un fichier et Écriture de fichiers.

Dans l’exemple suivant, le code de l’UDF utilise un modĂšle NLP pour dĂ©couvrir les entitĂ©s dans le texte. Le code renvoie un tableau de ces entitĂ©s. Pour configurer le modĂšle NLP afin de traiter le texte, le code utilise d’abord le module zipfile pour extraire le fichier du modĂšle (en_core_web_sm-2.3.1) d’un fichier .zip. Le code utilise ensuite le module spaCy pour charger le modĂšle Ă  partir du fichier.

Notez que le code Ă©crit le contenu des fichiers extraits dans le rĂ©pertoire /tmp créé pour la requĂȘte qui appelle cette fonction. Le code utilise des verrous de fichier pour garantir que l’extraction est synchronisĂ©e entre les processus de travail Python ; de cette façon, le contenu n’est dĂ©compressĂ© qu’une seule fois. Pour plus d’informations sur l’écriture de fichiers, voir Écriture de fichiers.

Pour en savoir plus sur le module zipfile, consultez la rĂ©fĂ©rence zipfile. Pour en savoir plus sur le module spaCy, consultez la documentation de l”API spaCy.

CrĂ©ez l’UDF avec un gestionnaire en ligne :

CREATE OR REPLACE FUNCTION py_spacy(str STRING)
  RETURNS ARRAY
  LANGUAGE PYTHON
  RUNTIME_VERSION = 3.9
  HANDLER = 'func'
  PACKAGES = ('spacy')
  IMPORTS = ('@spacy_stage/spacy_en_core_web_sm.zip')
AS $$
import fcntl
import os
import spacy
import sys
import threading
import zipfile

 # File lock class for synchronizing write access to /tmp.
 class FileLock:
   def __enter__(self):
       self._lock = threading.Lock()
       self._lock.acquire()
       self._fd = open('/tmp/lockfile.LOCK', 'w+')
       fcntl.lockf(self._fd, fcntl.LOCK_EX)

    def __exit__(self, type, value, traceback):
       self._fd.close()
       self._lock.release()

 # Get the location of the import directory. Snowflake sets the import
 # directory location so code can retrieve the location via sys._xoptions.
 IMPORT_DIRECTORY_NAME = "snowflake_import_directory"
 import_dir = sys._xoptions[IMPORT_DIRECTORY_NAME]

 # Get the path to the ZIP file and set the location to extract to.
 zip_file_path = import_dir + "spacy_en_core_web_sm.zip"
 extracted = '/tmp/en_core_web_sm'

 # Extract the contents of the ZIP. This is done under the file lock
 # to ensure that only one worker process unzips the contents.
 with FileLock():
    if not os.path.isdir(extracted + '/en_core_web_sm/en_core_web_sm-2.3.1'):
       with zipfile.ZipFile(zip_file_path, 'r') as myzip:
          myzip.extractall(extracted)

 # Load the model from the extracted file.
 nlp = spacy.load(extracted + "/en_core_web_sm/en_core_web_sm-2.3.1")

 def func(text):
    doc = nlp(text)
    result = []

    for ent in doc.ents:
       result.append((ent.text, ent.start_char, ent.end_char, ent.label_))
    return result
 $$;
Copy

Traitement des valeurs NULL¶

Le code suivant montre comment les valeurs NULL sont traitĂ©es. Pour plus d’informations, voir Valeurs NULL.

CrĂ©ez l’UDF :

CREATE OR REPLACE FUNCTION py_udf_null(a VARIANT)
  RETURNS STRING
  LANGUAGE PYTHON
  RUNTIME_VERSION = 3.9
  HANDLER = 'udf'
AS $$

def udf(a):
   if not a:
       return 'JSON null'
   elif getattr(a, "is_sql_null", False):
       return 'SQL null'
   else:
       return 'not null'
$$;
Copy

Appelez l’UDF :

SELECT py_udf_null(null);
Copy
+-------------------+
| PY_UDF_NULL(NULL) |
|-------------------|
| SQL null          |
+-------------------+
SELECT py_udf_null(parse_json('null'));
Copy
+---------------------------------+
| PY_UDF_NULL(PARSE_JSON('NULL')) |
|---------------------------------|
| JSON null                       |
+---------------------------------+
SELECT py_udf_null(10);
Copy
+-----------------+
| PY_UDF_NULL(10) |
|-----------------|
| not null        |
+-----------------+