La version de Python 2 utilisée par MaxCompute est Python 2.7. Cette rubrique explique comment écrire une fonction définie par l'utilisateur (UDF) en Python 2.
Structure du code d'une UDF
Vous pouvez utiliser MaxCompute Studio pour écrire le code d'une UDF en Python 2. Le code de l'UDF peut contenir les éléments suivants :
-
Déclaration d'encodage : facultative.
Le format de déclaration est
#coding:utf-8ou# -*- coding: utf-8 -*-. Ces deux formats sont équivalents. Si des caractères chinois apparaissent dans le code d'une UDF écrite en Python 2, une erreur se produit lors de l'exécution de l'UDF. Pour résoudre ce problème, vous devez ajouter une déclaration d'encodage dans l'en-tête du code. -
Importation de module : obligatoire.
Le code de l'UDF doit inclure
from odps.udf import annotate, qui sert à importer la signature de fonction. Cela permet à MaxCompute d'identifier la signature de fonction définie dans le code. Si vous souhaitez référencer des fichiers ou des tables dans le code de l'UDF, celui-ci doit inclurefrom odps.distcache import get_cache_fileoufrom odps.distcache import get_cache_table. -
Signature de fonction : obligatoire.
La signature de fonction suit le format
@annotate(<signature>). Le paramètresignaturedéfinit les types de données des paramètres d'entrée et de la valeur de retour de l'UDF. Pour plus d'informations sur les signatures de fonction, consultez la section Signatures de fonction et types de données. -
Classe Python personnalisée : obligatoire.
Une classe Python personnalisée constitue l'unité organisationnelle du code de l'UDF. Cette classe définit les variables et les méthodes nécessaires pour répondre à vos besoins métier. Dans le code de l'UDF, vous pouvez également référencer des bibliothèques tierces installées dans MaxCompute, ainsi que des fichiers ou des tables. Pour plus d'informations, consultez les sections Bibliothèques tierces ou Ressources de référence.
-
Méthode
evaluate: obligatoire.La méthode evaluate est contenue dans la classe Python personnalisée. La méthode
evaluatedéfinit les paramètres d'entrée et la valeur de retour de l'UDF. Chaque classe Python ne peut contenir qu'une seule méthodeevaluate.
Exemple de code :
#coding:utf-8
# Import the function signature.
from odps.udf import annotate
# The function signature.
@annotate("bigint,bigint->bigint")
# The custom Python class.
class MyPlus(object):
# The evaluate method.
def evaluate(self, arg0, arg1):
if None in (arg0, arg1):
return None
return arg0 + arg1
Limites
MaxCompute vous permet d'écrire des UDF Python 2 en Python 2.7 et d'exécuter le code de l'UDF dans un environnement sandbox. Dans cet environnement, les opérations suivantes sont interdites :
Lire des données depuis des fichiers locaux et y écrire des données.
Démarrer des sous-processus.
Démarrer des threads.
Activer la communication socket.
Utiliser d'autres systèmes pour appeler des UDF Python 2.
En raison de ces limites, le code que vous téléchargez doit être écrit à l'aide des bibliothèques standard de Python. Si des modules ou des modules d'extension C des bibliothèques standard de Python sont impliqués dans les opérations mentionnées ci-dessus, ces modules ne peuvent pas être utilisés. Tenez compte des points suivants concernant les modules des bibliothèques standard de Python :
Tous les modules implémentés sur la base des bibliothèques standard de Python et ne dépendant pas de modules d'extension sont disponibles.
-
Les modules d'extension C suivants sont disponibles :
array et audioop
binascii et bisect
cmath, _codecs_cn, _codecs_hk, _codecs_iso2022, _codecs_jp, _codecs_kr, _codecs_tw, _collections et cStringIO
datetime
_functools et future_builtins
_heapq et _hashlib
itertools
_json
_locale et _lsprof
math, _md5 et _multibytecodec
operator
_random
_sha256, _sha512, _sha, _struct et strop
time
unicodedata
_weakref
cPickle
Lorsque vous exécutez le code d'une UDF dans un environnement sandbox, la taille maximale des données pouvant être écrites dans la sortie standard (sys.stdout) ou la sortie d'erreur standard (
sys.stderr) est de 20 Ko. Si la taille dépasse 20 Ko, les caractères supplémentaires sont ignorés.
Bibliothèques tierces
Des bibliothèques tierces, telles que NumPy, sont installées dans l'environnement Python 2 de MaxCompute en complément des bibliothèques standard.
L'utilisation de bibliothèques tierces est soumise à certaines limites. Par exemple, lorsque vous utilisez une bibliothèque tierce, vous n'êtes pas autorisé à accéder aux données locales et vous ne pouvez utiliser que des ressources d'E/S réseau limitées. Les API associées dans les bibliothèques tierces sont désactivées.
Signatures de fonction et types de données
Format des signatures de fonction :
@annotate(<signature>)
Le paramètre signature est une chaîne qui spécifie les types de données des paramètres d'entrée et de la valeur de retour. Lors de l'exécution d'une UDF, les types de données des paramètres d'entrée et de la valeur de retour de l'UDF doivent correspondre aux types de données spécifiés dans la signature de fonction. La cohérence des types de données est vérifiée lors de l'analyse sémantique. Si les types de données ne correspondent pas, une erreur est renvoyée. Format d'une signature :
'arg_type_list -> type'
description des paramètres :
-
arg_type_list: spécifie les types de données des paramètres d'entrée. Si plusieurs paramètres d'entrée sont utilisés, leurs types de données sont séparés par des virgules (,). Les types de données suivants sont pris en charge : BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, DECIMAL, FLOAT, BINARY, DATE, DECIMAL(precision,scale), CHAR et VARCHAR. Les types de données complexes, tels que ARRAY, MAP et STRUCT, ainsi que les types de données complexes imbriqués, sont également pris en charge.arg_type_listpeut être représenté par un astérisque (*) ou laissé vide ('').Si
arg_type_listest représenté par un astérisque (*), un nombre aléatoire de paramètres d'entrée est autorisé.Si
arg_type_listest laissé vide (''), aucun paramètre d'entrée n'est utilisé.
type: spécifie le type de données de la valeur de retour. Pour une UDF, une seule colonne de valeurs est renvoyée. Les types de données suivants sont pris en charge : BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, DECIMAL, FLOAT, BINARY, DATE et DECIMAL(precision,scale). Les types de données complexes, tels que ARRAY, MAP et STRUCT, ainsi que les types de données complexes imbriqués, sont également pris en charge.
Lorsque vous écrivez le code d'une UDF, vous pouvez sélectionner un type de données en fonction de l'édition de type de données MaxCompute utilisée par votre projet MaxCompute. Pour plus d'informations sur les éditions de types de données MaxCompute et les types de données pris en charge dans chaque édition, consultez la section Éditions de types de données.
Le tableau suivant fournit des exemples de signatures de fonction valides.
|
Signature de fonction |
description |
|
|
Les types de données des paramètres d'entrée sont BIGINT et DOUBLE et le type de données de la valeur de retour est STRING. |
|
|
Un nombre aléatoire de paramètres d'entrée est utilisé et le type de données de la valeur de retour est STRING. |
|
|
Aucun paramètre d'entrée n'est utilisé et le type de données de la valeur de retour est DOUBLE. |
|
|
Le type de données des paramètres d'entrée est ARRAY<BIGINT> et le type de données de la valeur de retour est STRUCT<x:STRING, y:INT>. |
|
|
Aucun paramètre d'entrée n'est utilisé et le type de données de la valeur de retour est MAP<BIGINT, STRING>. |
Le tableau suivant décrit les correspondances entre les types de données pris en charge dans MaxCompute SQL et les types de données Python 2. Vous devez écrire les UDF Python en vous basant sur ces correspondances afin de garantir la cohérence des types de données.
|
Type de données MaxCompute SQL |
Type de données Python 2 |
|
BIGINT |
INT |
|
STRING |
STR |
|
DOUBLE |
FLOAT |
|
BOOLEAN |
BOOL |
|
DATETIME |
INT |
|
FLOAT |
FLOAT |
|
CHAR |
STR |
|
VARCHAR |
STR |
|
BINARY |
BYTEARRAY |
|
DATE |
INT |
|
DECIMAL |
DECIMAL.DECIMAL |
|
ARRAY |
LIST |
|
MAP |
DICT |
|
STRUCT |
COLLECTIONS.NAMEDTUPLE |
Le type DATETIME pris en charge dans MaxCompute SQL correspond au type de données Python INT. Une valeur de type INT suit le format UNIX, qui représente le nombre de millisecondes écoulées depuis le jeudi 1er janvier 1970 à 00:00:00. Vous pouvez traiter les données de type DATETIME à l'aide du module DATETIME des bibliothèques standard de Python.
Le paramètre
silentest ajouté àodps.udf.int(value). Si le paramètresilentest défini sur True et que le type de données devaluene peut pas être converti en type INT, la valeur None est renvoyée sans générer d'erreur.NULL dans MaxCompute SQL correspond à None dans Python 2.
Ressources de référence
Vous pouvez référencer des fichiers ou des tables dans le code d'une UDF Python 2 à l'aide du module odps.distcache.
-
odps.distcache.get_cache_file(resource_name): renvoie le contenu d'un fichier spécifié.-
resource_nameest une chaîne qui spécifie le nom d'un fichier existant dans votre projet MaxCompute. Si le nom du fichier n'est pas valide ou si le fichier n'existe pas, une erreur est renvoyée.RemarquePour référencer un fichier dans le code d'une UDF, vous devez déclarer le fichier lors de la création de l'UDF. Sinon, une erreur se produit lors de l'appel de l'UDF.
La valeur de retour est un objet de type fichier. Si cet objet n'est plus utilisé, vous devez appeler la méthode
closepour libérer le fichier ouvert.
Le code suivant montre comment référencer un fichier.
from odps.udf import annotate from odps.distcache import get_cache_file @annotate('bigint->string') class DistCacheExample(object): def __init__(self): cache_file = get_cache_file('test_distcache.txt') kv = {} for line in cache_file: line = line.strip() if not line: continue k, v = line.split() kv[int(k)] = v cache_file.close() self.kv = kv def evaluate(self, arg): return self.kv.get(arg) -
-
odps.distcache.get_cache_table(resource_name): renvoie le contenu d'une table spécifiée.resource_nameest une chaîne qui spécifie le nom d'une table existante dans votre projet MaxCompute. Si le nom de la table n'est pas valide ou si la table n'existe pas, une erreur est renvoyée.La valeur de retour est de type GENERATOR. L'appelant parcourt la table pour obtenir son contenu. Un enregistrement de type ARRAY est obtenu à chaque fois que l'appelant parcourt la table.
Le code suivant montre comment référencer une table.
from odps.udf import annotate from odps.distcache import get_cache_table @annotate('->string') class DistCacheTableExample(object): def __init__(self): self.records = list(get_cache_table('udf_test')) self.counter = 0 self.ln = len(self.records) def evaluate(self): if self.counter > self.ln - 1: return None ret = self.records[self.counter] self.counter += 1 return str(ret)
Processus de développement
Lorsque vous développez une UDF, vous devez effectuer les préparatifs, écrire le code de l'UDF, télécharger le programme Python, créer l'UDF, déboguer l'UDF et appeler l'UDF. MaxCompute vous permet d'utiliser plusieurs outils pour développer une UDF, tels que MaxCompute Studio, DataWorks et le client MaxCompute (odpscmd).
Le processus d'utilisation de divers outils pour développer des UDF en Python 2 est identique à celui du développement d'UDF en Python 3. Pour plus d'informations sur le processus de développement et des exemples sur la façon de développer une UDF en Python, consultez la section Processus de développement.
Pour plus d'informations sur l'utilisation de MaxCompute Studio pour développer et appeler une UDF en Python 2, consultez la section Développer une UDF Python.
Remarques d'utilisation
Après avoir développé une UDF Python 2, vous pouvez utiliser MaxCompute SQL pour appeler cette UDF. Vous pouvez appeler une UDF Python 2 en utilisant l'une des méthodes suivantes :
Utiliser une UDF dans un projet MaxCompute : la méthode est similaire à celle d'utilisation des fonctions intégrées. Vous pouvez utiliser une fonction définie par l'utilisateur de la même manière qu'une fonction intégrée.
Utiliser une UDF entre projets : utilisez une UDF du projet B dans le projet A. L'instruction suivante montre un exemple :
select B:udf_in_other_project(arg0, arg1) as res from table_t;. Pour plus d'informations sur le partage entre projets, consultez la section Accès aux ressources entre projets basé sur les packages.