Utilisez des packages Python tiers, tels que SciPy ou python-dateutil, dans PyODPS en les téléchargeant sous forme de ressources MaxCompute et en y faisant référence dans votre code. Pour savoir comment générer un package avec pyodps-pack, consultez la rubrique Générer un package tiers pour PyODPS.
Prérequis
Avant de commencer, assurez-vous d'avoir :
Choisir une méthode
Sélectionnez la méthode adaptée à votre scénario :
|
Scénario |
Méthode recommandée |
|
Nouveau projet, UDF Python ou DataFrame |
Utilisez |
|
Nœud PyODPS DataWorks avec packages intégrés |
Utilisez la méthode intégrée à DataWorks ou |
|
Projet existant avec des fichiers WHL téléchargés manuellement |
Téléchargement manuel (uniquement pour la maintenance des projets existants ; utilisez |
Télécharger un package tiers
Avant de référencer un package tiers, téléchargez-le sur MaxCompute en tant que ressource d'archive. Utilisez l'une des méthodes suivantes :
-
Téléchargement par code. Remplacez
packages.tar.gzpar le chemin et le nom de votre fichier de package.import os from odps import ODPS # Load credentials from environment variables. # Avoid hardcoding your AccessKey ID or AccessKey secret in code. o = ODPS( os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'), os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'), project='<your-default-project>', endpoint='<your-end-point>', ) o.create_resource("test_packed.tar.gz", "archive", fileobj=open("packages.tar.gz", "rb")) Téléchargement via DataWorks. Consultez la section Étape 1 : Créer une ressource ou télécharger une ressource existante.
Référencer un package tiers dans une UDF Python
Pour utiliser un package tiers dans une fonction définie par l'utilisateur (UDF) Python, modifiez la classe UDF :
Ajoutez le chemin du package à
sys.pathdans la méthode__init__.Placez l'instruction d'importation à l'intérieur du corps de la fonction (la fonction
evaluateou la méthodeprocess).
L'instruction d'importation doit figurer à l'intérieur du corps de la fonction, et non au début du fichier. Les packages tiers ne sont disponibles qu'à l'exécution. Lorsque MaxCompute analyse l'UDF, l'environnement d'analyse n'inclut pas les packages tiers ; par conséquent, une importation au niveau supérieur provoque une erreur.
Exemple : utiliser SciPy dans une UDF
Cet exemple utilise la fonction psi de SciPy dans une UDF.
-
Empaquetez SciPy.
pyodps-pack -o scipy-bundle.tar.gz scipy -
Rédigez le code UDF et enregistrez-le sous le nom
test_psi_udf.py.import sys from odps.udf import annotate @annotate("double->double") class MyPsi(object): def __init__(self): # Add the package path to sys.path. # MaxCompute decompresses archive resources into folders under the work/ directory. # The folder name matches the resource name. # packages/ is the subdirectory created by pyodps-pack. sys.path.insert(0, "work/scipy-bundle.tar.gz/packages") def evaluate(self, arg0): # Place the import statement inside the function body. from scipy.special import psi return float(psi(arg0)) Téléchargez
test_psi_udf.pyen tant que ressource Python etscipy-bundle.tar.gzen tant que ressource d'archive.-
Créez l'UDF, référencez les deux ressources et définissez le nom de la classe sur
test_psi_udf.MyPsi. Effectuez cette opération dans un nœud PyODPS ou sur le client MaxCompute.-
Dans un nœud PyODPS :
import os from odps import ODPS # Load credentials from environment variables. # Avoid hardcoding your AccessKey ID or AccessKey secret in code. o = ODPS( os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'), os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'), project='<your-default-project>', endpoint='<your-end-point>', ) bundle_res = o.create_resource( "scipy-bundle.tar.gz", "archive", fileobj=open("scipy-bundle.tar.gz", "rb") ) udf_res = o.create_resource( "test_psi_udf.py", "py", fileobj=open("test_psi_udf.py", "rb") ) o.create_function( "test_psi_udf", class_type="test_psi_udf.MyPsi", resources=[bundle_res, udf_res] ) -
Sur le client MaxCompute :
add archive scipy-bundle.tar.gz; add py test_psi_udf.py; create function test_psi_udf as test_psi_udf.MyPsi using test_psi_udf.py,scipy-bundle.tar.gz;
-
-
Exécutez l'UDF dans une instruction SQL.
set odps.pypy.enabled=false; set odps.isolation.session.enable=true; select test_psi_udf(sepal_length) from iris;
Référencer un package tiers dans PyODPS DataFrame
Transmettez le paramètre libraries à la méthode execute ou persist. L'exemple suivant utilise la méthode map ; la procédure est identique pour les méthodes apply et map_reduce.
-
Empaquetez SciPy.
pyodps-pack -o scipy-bundle.tar.gz scipy -
Exécutez le code suivant pour appliquer le package à une opération DataFrame. Cet exemple calcule
psi(col1)sur une table nomméetest_float_col, qui possède une seule colonne de type FLOAT.import os from odps import ODPS, options def my_psi(v): from scipy.special import psi return float(psi(v)) # Skip this setting if isolation is already enabled for your project. options.sql.settings = {"odps.isolation.session.enable": True} # Load credentials from environment variables. # Avoid hardcoding your AccessKey ID or AccessKey secret in code. o = ODPS( os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'), os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'), project='<your-default-project>', endpoint='<your-end-point>', ) df = o.get_table("test_float_col").to_df() # Execute and return the result. df.col1.map(my_psi).execute(libraries=["scipy-bundle.tar.gz"]) # Save the result to another table. df.col1.map(my_psi).persist("result_table", libraries=["scipy-bundle.tar.gz"])Les données d'entrée se présentent comme suit :
col1 0 3.75 1 2.51 -
(Facultatif) Pour utiliser le même package pour toutes les opérations DataFrame de la session, définissez le paramètre global.
from odps import options options.df.libraries = ["scipy-bundle.tar.gz"]
Référencer un package tiers dans DataWorks
Un nœud PyODPS DataWorks fournit des packages tiers intégrés. Pour utiliser un package qui n'est pas intégré, appelez la méthode load_resource_package. Pour plus de détails, consultez la section Utiliser un package tiers.
Télécharger et référencer manuellement un package tiers
Suivez ces instructions uniquement pour les projets existants qui utilisent déjà des dépendances WHL téléchargées manuellement, ou pour les environnements exécutant une version antérieure de MaxCompute qui ne prend pas en charge les packages binaires. Pour les nouveaux projets, utilisez plutôt pyodps-pack .
Cet exemple utilise python-dateutil dans la méthode map.
-
Téléchargez python-dateutil et ses dépendances dans un répertoire local. Exécutez cette commande sous Linux pour vous assurer que les packages sont compatibles avec le système d'exploitation Linux.
pip download python-dateutil -d /to/path/Deux packages sont téléchargés :
six-1.10.0-py2.py3-none-any.whletpython_dateutil-2.5.3-py2.py3-none-any.whl. -
Téléchargez les packages sur MaxCompute.
-
Méthode 1 : Utiliser le code.
# Make sure the file name extensions are valid. odps.create_resource('six.whl', 'file', file_obj=open('six-1.10.0-py2.py3-none-any.whl', 'rb')) odps.create_resource('python_dateutil.whl', 'file', file_obj=open('python_dateutil-2.5.3-py2.py3-none-any.whl', 'rb')) Méthode 2 : Utiliser DataWorks. Consultez la section Étape 1 : Créer une ressource ou télécharger une ressource existante.
-
-
Référencez les packages dans votre code. Cet exemple analyse les chaînes de dates à partir d'une colonne DataFrame.
-
Définir les bibliothèques globalement :
from odps import options def get_year(t): from dateutil.parser import parse return parse(t).strftime('%Y') options.df.libraries = ['six.whl', 'python_dateutil.whl'] df.datestr.map(get_year).execute()Sortie :
datestr 0 2016 1 2015 -
Transmettre les bibliothèques par appel :
def get_year(t): from dateutil.parser import parse return parse(t).strftime('%Y') df.datestr.map(get_year).execute(libraries=['six.whl', 'python_dateutil.whl'])Sortie :
datestr 0 2016 1 2015
-
Compatibilité des packages binaires
Par défaut, PyODPS prend en charge les bibliothèques Python qui contiennent uniquement du code Python sans opérations sur les fichiers. Les versions ultérieures de MaxCompute prennent également en charge les bibliothèques contenant du code binaire ou effectuant des opérations sur les fichiers. Les noms de bibliothèque doivent inclure un suffixe spécifique à la plateforme.
Le tableau suivant répertorie les suffixes pris en charge par plateforme et par version Python.
|
Plateforme |
Version Python |
Suffixe pris en charge |
|
RHEL 5 x86_64 |
Python 2.7 |
cp27-cp27m-manylinux1_x86_64 |
|
RHEL 5 x86_64 |
Python 3.7 |
cp37-cp37m-manylinux1_x86_64 |
|
RHEL 7 x86_64 |
Python 2.7 |
cp27-cp27m-manylinux1_x86_64, cp27-cp27m-manylinux2010_x86_64, cp27-cp27m-manylinux2014_x86_64 |
|
RHEL 7 x86_64 |
Python 3.7 |
cp37-cp37m-manylinux1_x86_64, cp37-cp37m-manylinux2010_x86_64, cp37-cp37m-manylinux2014_x86_64 |
|
RHEL 7 Arm64 |
Python 3.7 |
cp37-cp37m-manylinux2014_aarch64 |
Tous les packages WHL doivent être téléchargés sur MaxCompute en tant que ressources d'archive. Avant le téléchargement, renommez chaque fichier WHL en fichier ZIP en modifiant son extension. Définissez également odps.isolation.session.enable sur True pour la tâche ou votre projet.
L'exemple suivant télécharge et utilise SciPy en tant que package binaire.
# Binary packages must be uploaded as archive resources.
# Rename the .whl file to .zip before uploading.
odps.create_resource('scipy.zip', 'archive', file_obj=open('scipy-0.19.0-cp27-cp27m-manylinux1_x86_64.whl', 'rb'))
# Skip this setting if isolation is already enabled for your project.
options.sql.settings = { 'odps.isolation.session.enable': True }
def my_psi(value):
# Place the import statement inside the function to avoid runtime errors
# caused by structural differences in binary packages across operating systems.
from scipy.special import psi
return float(psi(value))
df.float_col.map(my_psi).execute(libraries=['scipy.zip'])
Pour empaqueter des packages binaires contenant uniquement du code source dans des fichiers WHL, exécutez la commande suivante sous Linux. Les fichiers WHL construits sur macOS ou Windows ne peuvent pas être utilisés dans MaxCompute.
python setup.py bdist_wheel