Fonctions définies par l'utilisateur en Python
Une fonction définie par l'utilisateur (UDF) Python vous permet d'implémenter une fonction scalaire en Python et de l'utiliser dans une requête SQL. Les UDF Python sont semblables aux UDF SQL et JavaScript, mais avec des fonctionnalités supplémentaires. Les UDF Python vous permettent d'installer des bibliothèques tierces à partir de l'index de packages Python (PyPI) et d'accéder à des services externes à l'aide d'une connexion à une ressource Cloud.
Les UDF Python sont créées et exécutées sur des ressources gérées BigQuery.
Limites
python-3.11
est le seul environnement d'exécution compatible.- Vous ne pouvez pas créer d'UDF Python temporaire.
- Vous ne pouvez pas utiliser de fonction définie par l'utilisateur Python avec une vue matérialisée.
- Les résultats d'une requête qui appelle une UDF Python ne sont pas mis en cache, car la valeur renvoyée par une UDF Python est toujours considérée comme non déterministe.
- Les UDF Python ne sont pas entièrement compatibles avec les vues
INFORMATION_SCHEMA
. - Vous ne pouvez pas créer ni mettre à jour une UDF Python à l'aide de l'API Routine.
- VPC Service Controls n'est pas compatible.
- Les clés de chiffrement gérées par le client (CMEK) ne sont pas prises en charge.
- Les types de données suivants ne sont pas acceptés :
JSON
,RANGE
,INTERVAL
etGEOGRAPHY
. - Les conteneurs qui exécutent des UDF Python ne peuvent être configurés qu'avec 2 vCPU et 8 Gi.
Rôles IAM requis
Les rôles IAM requis dépendent de votre statut (propriétaire ou utilisateur d'une UDF Python). Un propriétaire d'UDF Python crée ou met à jour une UDF. Un utilisateur d'UDF Python appelle une UDF créée par un autre utilisateur.
Des rôles supplémentaires sont également requis si vous créez ou exécutez une UDF Python qui fait référence à une connexion à une ressource cloud.
Propriétaires des UDF
Si vous créez ou mettez à jour une UDF Python, les rôles IAM prédéfinis suivants doivent être accordés sur la ressource appropriée :
Rôle | Autorisations requises | Ressource |
---|---|---|
Éditeur de données BigQuery (roles/bigquery.dataEditor )
|
|
Ensemble de données dans lequel la fonction définie par l'utilisateur Python est créée ou mise à jour. |
Utilisateur de job BigQuery (roles/bigquery.jobUser )
|
|
Projet dans lequel vous exécutez l'instruction CREATE FUNCTION .
|
Administrateur de connexion BigQuery (roles/bigquery.connectionAdmin )
|
|
La connexion que vous autorisez permet d'accéder à une ressource externe. Cette connexion n'est requise que si votre UDF utilise la clause WITH CONNECTION pour accéder à un service externe.
|
Utilisateurs UDF
Si vous appelez une UDF Python, les rôles IAM prédéfinis suivants doivent être accordés sur la ressource appropriée :
Rôle | Autorisations requises | Ressource |
---|---|---|
Utilisateur BigQuery (roles/bigquery.user ) |
bigquery.jobs.create pour exécuter une tâche de requête qui référence la UDF;utilisateur. |
Projet dans lequel vous exécutez un job de requête qui appelle la UDF par l'utilisateur Python. |
Lecteur de données BigQuery (roles/bigquery.dataViewer ) |
bigquery.routines.get pour exécuter une UDF créée par une autre personne. |
Ensemble de données dans lequel la fonction définie par l'utilisateur Python est stockée. |
Utilisateur de connexion BigQuery (roles/bigquery.connectionUser ) |
bigquery.connections.use pour exécuter une UDF Python qui référence une connexion à une ressource Cloud. |
Connexion aux ressources cloud référencée par l'UDF Python. Cette connexion n'est requise que si votre UDF fait référence à une connexion. |
Pour en savoir plus sur les rôles dans BigQuery, consultez Rôles IAM prédéfinis.
Créer une UDF Python persistante
Lorsque vous créez une UDF Python, respectez les règles suivantes :
Le corps de l'UDF Python doit être une chaîne littérale entre guillemets représentant le code Python. Pour en savoir plus sur les littéraux de chaîne entre guillemets, consultez Formats pour les littéraux entre guillemets.
Le corps de la fonction Python définie par l'utilisateur doit inclure une fonction Python utilisée dans l'argument
entry_point
de la liste des options de la fonction Python définie par l'utilisateur.Une version d'environnement d'exécution Python doit être spécifiée dans l'option
runtime_version
. La seule version d'exécution Python compatible estpython-3.11
. Pour obtenir la liste complète des options disponibles, consultez la liste des options de fonction pour l'instructionCREATE FUNCTION
.
Pour créer une UDF Python persistante, utilisez l'instruction CREATE FUNCTION
sans le mot clé TEMP
ou TEMPORARY
. Pour supprimer une UDF Python persistante, utilisez l'instruction DROP FUNCTION
.
Lorsque vous créez une UDF Python à l'aide de l'instruction CREATE FUNCTION
, BigQuery crée ou met à jour une image de conteneur basée sur une image de base. Le conteneur est créé sur l'image de base à l'aide de votre code et de toutes les dépendances de package spécifiées. La création du conteneur est un processus de longue durée. La première requête après l'exécution de l'instruction CREATE FUNCTION
peut attendre automatiquement que l'image soit complète. Sans aucune dépendance externe, l'image de conteneur devrait généralement être créée en moins d'une minute.
Exemple
Pour voir un exemple de création d'une UDF Python persistante, choisissez l'une des options suivantes :
Console
L'exemple suivant crée une fonction Python persistante définie par l'utilisateur nommée multiplyInputs
et appelle cette UDF à partir d'une instruction SELECT
:
Accédez à la page BigQuery.
Dans l'éditeur de requête, saisissez l'instruction
CREATE FUNCTION
suivante :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;
Remplacez PROJECT_ID.DATASET_ID par l'ID de votre projet et l'ID de l'ensemble de données.
Cliquez sur
Exécuter.Cet exemple génère la sortie suivante :
+-----+-----+--------------+ | x | y | product | +-----+-----+--------------+ | 1 | 5 | 5.0 | | 2 | 10 | 20.0 | | 3 | 15 | 45.0 | +-----+-----+--------------+
BigQuery DataFrames
L'exemple suivant utilise BigQuery DataFrames pour transformer une fonction personnalisée en UDF Python :
Créer une UDF Python vectorisée
Vous pouvez implémenter votre UDF Python pour traiter un lot de lignes au lieu d'une seule ligne en utilisant la vectorisation. La vectorisation peut améliorer les performances des requêtes.
Pour contrôler le comportement de regroupement par lot, spécifiez le nombre maximal de lignes dans chaque lot à l'aide de l'option max_batching_rows
dans la liste d'options CREATE OR REPLACE FUNCTION
.
Si vous spécifiez max_batching_rows
, BigQuery détermine le nombre de lignes d'un lot, dans la limite de max_batching_rows
. Si max_batching_rows
n'est pas spécifié, le nombre de lignes à regrouper est déterminé automatiquement.
Une UDF Python vectorisée comporte un seul argument pandas.DataFrame
qui doit être annoté. L'argument pandas.DataFrame
comporte le même nombre de colonnes que les paramètres UDF Python définis dans l'instruction CREATE FUNCTION
. Les noms de colonnes de l'argument pandas.DataFrame
sont identiques à ceux des paramètres de l'UDF.
Votre fonction doit renvoyer un pandas.Series
ou un pandas.DataFrame
à une seule colonne avec le même nombre de lignes que l'entrée.
L'exemple suivant crée une UDF Python vectorisée nommée multiplyInputs
avec deux paramètres : x
et y
:
Accédez à la page BigQuery.
Dans l'éditeur de requête, saisissez l'instruction
CREATE FUNCTION
suivante :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'] ''';
Remplacez PROJECT_ID.DATASET_ID par l'ID de votre projet et l'ID de l'ensemble de données.
L'appel de l'UDF est identique à celui de l'exemple précédent.
Cliquez sur
Exécuter.
Types de données compatibles avec les fonctions Python définies par l'utilisateur
Le tableau suivant définit le mappage entre les types de données BigQuery, les types de données Python et les types de données Pandas :
Type de données BigQuery | Type de données Python intégré utilisé par les UDF standards | Type de données Pandas utilisé par l'UDF vectorisée | Type de données PyArrow utilisé pour ARRAY et STRUCT dans les UDF vectorisées |
---|---|---|---|
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 |
Paramètre de fonction : Valeur renvoyée par la fonction : |
Paramètre de la fonction : Valeur renvoyée par la fonction : |
TimestampType(timestamp[us]) , avec fuseau horaire |
DATE |
datetime.date |
date32[pyarrow] |
DataType(date32[day]) |
TIME |
datetime.time |
time64[pyarrow] |
Time64Type(time64[us]) |
DATETIME |
datetime.datetime (sans fuseau horaire) |
timestamp[us][pyarrow] |
TimestampType(timestamp[us]) , sans fuseau horaire |
ARRAY |
list |
list<...>[pyarrow] , où le type de données de l'élément est pandas.ArrowDtype |
ListType |
STRUCT |
dict |
struct<...>[pyarrow] , où le type de données du champ est pandas.ArrowDtype |
StructType |
Versions d'exécution compatibles
Les UDF Python BigQuery sont compatibles avec l'environnement d'exécution python-3.11
. Cette version Python inclut des packages préinstallés supplémentaires. Pour les bibliothèques système, vérifiez l'image de base de l'environnement d'exécution.
Version d'exécution | Version Python | Inclut | Image de base de l'environnement d'exécution |
---|---|---|---|
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 |
Utiliser des packages tiers
Vous pouvez utiliser la liste d'options CREATE FUNCTION
pour utiliser des modules autres que ceux fournis par la bibliothèque standard Python et les packages préinstallés. Vous pouvez installer des packages à partir de l'index de packages Python (PyPI) ou importer des fichiers Python depuis Cloud Storage.
Installer un package à partir de l'index de packages Python
Lorsque vous installez un package, vous devez fournir son nom et vous pouvez éventuellement fournir sa version à l'aide des spécificateurs de version de package Python.
Si le package se trouve dans l'environnement d'exécution, il est utilisé, sauf si une version spécifique est spécifiée dans la liste d'options CREATE FUNCTION
. Si aucune version de package n'est spécifiée et que le package n'est pas dans l'environnement d'exécution, la dernière version disponible est utilisée. Seuls les packages au format binaire wheels sont acceptés.
L'exemple suivant vous montre comment créer une UDF Python qui installe le package scipy
à l'aide de la liste d'options CREATE OR REPLACE FUNCTION
:
Accédez à la page BigQuery.
Dans l'éditeur de requête, saisissez l'instruction
CREATE FUNCTION
suivante :CREATE FUNCTION `PROJECT_ID.DATASET_ID`.area(radius FLOAT64) RETURNS FLOAT64 LANGUAGE python OPTIONS (entry_point='area_handler', runtime_version='python-3.11', packages=['scipy==1.15.3']) AS r""" import scipy def area_handler(radius): return scipy.constants.pi*radius*radius """; SELECT `PROJECT_ID.DATASET_ID`.area(4.5);
Remplacez PROJECT_ID.DATASET_ID par l'ID de votre projet et l'ID de l'ensemble de données.
Cliquez sur
Exécuter.
Importer des fichiers Python supplémentaires en tant que bibliothèques
Vous pouvez étendre vos UDF Python à l'aide de la liste d'options de fonction en important des fichiers Python depuis Cloud Storage.
Dans le code Python de votre UDF, vous pouvez importer les fichiers Python depuis Cloud Storage en tant que modules à l'aide de l'instruction import suivie du chemin d'accès à l'objet Cloud Storage. Par exemple, si vous importez gs://BUCKET_NAME/path/to/lib1.py
, votre instruction d'importation sera import path.to.lib1
.
Le nom de fichier Python doit être un identifiant Python. Chaque nom folder
dans le nom de l'objet (après /
) doit être un identifiant Python valide. Dans la plage ASCII (U+0001..U+007F), les caractères suivants peuvent être utilisés dans les identifiants :
- Lettres majuscules et minuscules de A à Z.
- Tirets du 8.
- Les chiffres de zéro à neuf, mais un nombre ne peut pas figurer en premier caractère de l'identifiant.
L'exemple suivant vous montre comment créer une UDF Python qui importe le package de la bibliothèque cliente lib1.py
à partir d'un bucket Cloud Storage nommé my_bucket
:
Accédez à la page BigQuery.
Dans l'éditeur de requête, saisissez l'instruction
CREATE FUNCTION
suivante :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); """;
Remplacez PROJECT_ID.DATASET_ID par l'ID de votre projet et l'ID de l'ensemble de données.
Cliquez sur
Exécuter.
Configurer les limites de conteneur pour les UDF Python
Vous pouvez utiliser la liste d'options CREATE FUNCTION
pour spécifier les limites de processeur et de mémoire pour les conteneurs qui exécutent des UDF Python.
Par défaut, la mémoire allouée à chaque instance de conteneur est de 512 Mio et le processeur alloué est de 0,33 processeur virtuel.
L'exemple suivant crée une UDF Python à l'aide de la liste d'options CREATE FUNCTION
pour spécifier les limites du conteneur :
Accédez à la page BigQuery.
Dans l'éditeur de requête, saisissez l'instruction
CREATE FUNCTION
suivante :CREATE FUNCTION `PROJECT_ID.DATASET_ID`.resizeImage(image BYTES) RETURNS BYTES LANGUAGE python OPTIONS (entry_point='resize_image', runtime_version='python-3.11', packages=['Pillow==11.2.1'], container_memory='2Gi', container_cpu=1) AS r""" import io from PIL import Image def resize_image(image_bytes): img = Image.open(io.BytesIO(image_bytes)) resized_img = img.resize((256, 256), Image.Resampling.LANCZOS) output_stream = io.BytesIO() resized_img.convert('RGB').save(output_stream, format='JPEG') return output_stream.getvalue() """;
Remplacez PROJECT_ID.DATASET_ID par l'ID de votre projet et l'ID de l'ensemble de données.
Cliquez sur
Exécuter.
Valeurs de processeur acceptées
Les UDF Python acceptent les valeurs fractionnaires de processeur comprises entre 0.33
et 1.0
, ainsi que les valeurs non fractionnaires de processeur 1
et 2
. Les valeurs d'entrée fractionnaires sont arrondies à deux décimales avant d'être appliquées au conteneur.
Valeurs de mémoire acceptées
Les conteneurs de fonctions Python définies par l'utilisateur sont compatibles avec les valeurs de mémoire au format suivant : <integer_number><unit>
. L'unité doit être l'une des valeurs suivantes : Mi
, M
, Gi
ou G
. La quantité de mémoire minimale que vous pouvez configurer est de 256 Mio.
La quantité maximale de mémoire que vous pouvez configurer est de huit gibioctets (8 Gio).
En fonction de la valeur de mémoire que vous choisissez, vous devez également spécifier la quantité minimale de processeur. Le tableau suivant indique les valeurs minimales de processeur pour chaque valeur de mémoire :
Mémoire | Processeur minimum |
---|---|
512 MiB or less |
0.33 |
More than 512 MiB |
0.5 |
More than 1 GiB |
1 |
More than 4 GiB |
2 |
Appeler Trusted Cloud by S3NS ou des services en ligne dans le code Python
Une UDF Python accède à un service Trusted Cloud by S3NS ou à un service externe à l'aide du compte de service Connexion de ressource cloud. Le compte de service de la connexion doit disposer des autorisations nécessaires pour accéder au service. Les autorisations requises varient en fonction du service auquel vous accédez et des API appelées à partir de votre code Python.
Si vous créez une UDF Python sans utiliser de connexion à une ressource Cloud, la fonction est exécutée dans un environnement qui bloque l'accès au réseau. Si votre UDF accède à des services en ligne, vous devez la créer avec une connexion à une ressource Cloud. Sinon, la fonction définie par l'utilisateur ne pourra pas accéder au réseau tant qu'un délai de connexion interne ne sera pas atteint.
L'exemple suivant montre comment accéder au service Cloud Translation à partir d'une UDF Python. Cet exemple comporte deux projets : un projet nommé my_query_project
dans lequel vous créez la fonction définie par l&#UDF et la connexion à la ressource Cloud, et un projet dans lequel vous exécutez Cloud Translation nommé my_translate_project
.
Créer une connexion de ressource Cloud
Commencez par créer une connexion de ressource Cloud dans my_query_project
. Pour créer la connexion à la ressource cloud, suivez les étapes décrites sur la page Créer une connexion à une ressource cloud.
Une fois la connexion créée, ouvrez-la, puis copiez l'ID du compte de service dans le volet Informations de connexion. Vous aurez besoin de cet ID lorsque vous configurerez les autorisations pour la connexion. Lorsque vous créez une ressource de connexion, BigQuery crée un compte de service système unique et l'associe à la connexion.
Accorder l'accès au compte de service de la connexion
Pour accorder au compte de service de connexion aux ressources Cloud l'accès à vos projets, attribuez-lui le rôle d'utilisateur de l'utilisation du service (roles/serviceusage.serviceUsageConsumer
) dans my_query_project
et le rôle d'utilisateur de l'API Cloud Translation (roles/cloudtranslate.user
) dans my_translate_project
.
Accédez à la page IAM.
Vérifiez que
my_query_project
est sélectionné.Cliquez sur
Accorder l'accès.Dans le champ Nouveaux comptes principaux, saisissez l'ID du compte de service de la connexion de ressource cloud que vous avez copié précédemment.
Dans le champ Sélectionner un rôle, choisissez Utilisation du service, puis sélectionnez Consommateur d'utilisation du service.
Cliquez sur Enregistrer.
Dans le sélecteur de projet, sélectionnez
my_translate_project
.Accédez à la page IAM.
Cliquez sur
Accorder l'accès.Dans le champ Nouveaux comptes principaux, saisissez l'ID du compte de service de la connexion de ressource cloud que vous avez copié précédemment.
Dans le champ Sélectionner un rôle, sélectionnez Cloud Translation, puis Utilisateur de l'API Cloud Translation.
Cliquez sur Enregistrer.
Créer une UDF Python qui appelle le service Cloud Translation
Dans my_query_project
, créez une UDF Python qui appelle le service Cloud Translation à l'aide de votre connexion à une ressource cloud.
Accédez à la page BigQuery.
Saisissez l'instruction
CREATE FUNCTION
suivante dans l'éditeur de requête :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;
Remplacez les éléments suivants :
PROJECT_ID.DATASET_ID
: ID de votre projet et de votre ensemble de donnéesREGION.CONNECTION_ID
: région et ID de votre connexion
Cliquez sur
Exécuter.Le résultat doit se présenter sous la forme suivante :
+--------------------------+-------------------------------+ | text | translated_text | +--------------------------+-------------------------------+ | Hello | Hola | | Good morning | Buen dia | | Goodbye | Adios | +--------------------------+-------------------------------+
Pays acceptés
Les UDF Python sont compatibles avec tous les emplacements BigQuery multirégionaux et régionaux.
Tarifs
Les UDF Python sont proposées sans frais supplémentaires.
Lorsque la facturation est activée, les conditions suivantes s'appliquent :
- Les frais liés aux UDF Python sont facturés à l'aide du SKU Services BigQuery.
- Les frais sont proportionnels à la quantité de calcul et de mémoire consommée lorsque l'UDF Python est appelée.
- Les clients des UDF Python sont également facturés pour la création ou la recréation de l'image de conteneur UDF. Ces frais sont proportionnels aux ressources utilisées pour créer l'image avec le code et les dépendances du client.
- Si les UDF Python entraînent un trafic sortant vers un réseau externe ou Internet, vous verrez également des frais de sortie Internet Premium de Cloud Networking.