MaxCompute admite el desarrollo de funciones definidas por el usuario (UDF) en Python 3 para implementar lógica de negocio personalizada.
Estructura del código de una UDF
Utilice MaxCompute Studio para escribir una UDF en Python 3. El código debe contener los siguientes componentes:
-
Importación de módulos: obligatorio.
El código de la UDF debe incluir
from odps.udf import annotate, que se usa para importar la firma de la función. De esta manera, MaxCompute puede identificar la firma definida en el código. Si desea hacer referencia a archivos o tablas dentro de la UDF, el código también debe incluirfrom odps.distcache import get_cache_fileofrom odps.distcache import get_cache_table. -
Firma de la función: obligatorio.
El formato es
@annotate(<signature>), dondesignaturedefine los tipos de datos de los parámetros de entrada y del valor de retorno. Para obtener más información sobre las firmas de función, consulte Function signatures and data types. -
Clase de Python personalizada: obligatorio.
Esta clase organiza el código de la UDF y define las variables y los métodos que implementan su lógica de negocio. También puede hacer referencia a una biblioteca de terceros integrada o a recursos de archivos y tablas dentro del código. Para obtener más información, consulte Third-party library o Reference resources.
-
Método
evaluate: obligatorio.Este método se incluye dentro de la clase de Python personalizada. El método
evaluatedefine los parámetros de entrada y el valor de retorno de la UDF. Cada clase de Python solo puede contener un métodoevaluate.
A continuación se muestra un ejemplo de código de una UDF.
# Import the function signature module.
from odps.udf import annotate
# Define the function signature.
@annotate("bigint,bigint->bigint")
# Define the custom Python class.
class MyPlus(object):
# Implement the evaluate method.
def evaluate(self, arg0, arg1):
if None in (arg0, arg1):
return None
return arg0 + arg1
Límites
-
Acceso a Internet mediante UDF
De forma predeterminada, MaxCompute no permite acceder a Internet mediante UDF. Si necesita este acceso, complete el formulario de solicitud de conexión de red según sus requisitos de negocio y envíe la solicitud. El equipo de soporte técnico de MaxCompute se pondrá en contacto con usted a la brevedad para habilitar la conectividad de red. Para obtener más información sobre cómo completar el formulario de solicitud de conexión de red, consulte Network connection process.
-
Acceso a una VPC mediante UDF
Por defecto, MaxCompute no permite acceder a recursos en VPC mediante UDF. Para lograrlo, debe establecer una conexión de red entre MaxCompute y la VPC. Para obtener más información sobre las operaciones relacionadas, consulte Access VPC resources from a UDF.
-
Lectura de datos de tablas mediante UDF, UDAF o UDTF
No es posible usar UDF, UDAF ni UDTF para leer datos de los siguientes tipos de tablas:
Tablas en las que se aplicó evolución de esquema
Tablas que contienen tipos de datos complejos
Tablas que contienen tipos de datos JSON
Tablas transaccionales
Notas de uso
Python 3 no es compatible con Python 2, por lo que no se pueden usar ambos en la misma instrucción SQL. Considere esta compatibilidad antes de cambiar de versión.
Python 2 llegó al final de su vida útil (EOL) a principios de 2020. Se recomienda migrar sus proyectos según el tipo de cada uno.
Desarrollo de UDF: flujo de trabajo general
El desarrollo de una UDF implica preparar el entorno, escribir el código, cargar y registrar la UDF y, finalmente, invocarla. En las siguientes secciones se detalla este flujo de trabajo con MaxCompute Studio, DataWorks y odpscmd.
MaxCompute Studio
-
Requisitos previos
Instale MaxCompute Studio y conéctelo a un proyecto de MaxCompute antes de empezar. Para obtener más información, consulte los siguientes temas:
-
Escriba el código de la UDF.
En el panel Project, dentro del directorio MaxCompute Studio, haga clic derecho en scripts y seleccione .
En el cuadro de diálogo Create new MaxCompute python class, introduzca un nombre de clase en Name, seleccione Python UDF como tipo y haga clic en OK.
-
Escriba el código de la UDF en el editor.
from odps.udf import annotate @annotate("string,bigint->string") class GetUrlChar(object): def evaluate(self, url, n): if n == 0: return "" try: index = url.find(".htm") if index < 0: return "" a = url[:index] index = a.rfind("/") b = a[index + 1:] c = b.split("-") if len(c) < n: return "" return c[-n] except Exception: return "Internal error"NotaPara obtener información sobre cómo depurar UDF de Python de forma local, consulte Test a UDF.
-
Cargue y registre la UDF.
Haga clic derecho en el programa de Python correspondiente y seleccione Deploy to server…. Configure el nombre de la función y haga clic en OK. Para obtener más información, consulte Upload a file and register a function.
En este ejemplo, el nombre de la función se establece en UDF_GET_URL_CHAR.
-
Invoque la UDF.
En el panel de navegación izquierdo, haga clic en Project Explore. Haga clic derecho en el proyecto de MaxCompute correspondiente, seleccione Open Console y luego introduzca y ejecute la instrucción SQL para invocar la UDF.
SET odps.sql.python.version=cp37; -- This command is required to enable Python 3 for the UDF. SELECT UDF_GET_URL_CHAR("http://www.taobao.com/a.htm", 1);Se devuelve el siguiente resultado:
+-----+ | _c0 | +-----+ | a | +-----+
DataWorks
-
Requisitos previos
Active DataWorks y vincúlelo a un proyecto de MaxCompute antes de empezar. Para obtener más información, consulte Connect to MaxCompute by using DataWorks.
-
Escriba el código de la UDF.
Puede desarrollar el código de la UDF en cualquier herramienta de desarrollo de Python y empaquetarlo. A continuación se muestra un ejemplo de código.
from odps.udf import annotate @annotate("string,bigint->string") class GetUrlChar(object): def evaluate(self, url, n): if n == 0: return "" try: index = url.find(".htm") if index < 0: return "" a = url[:index] index = a.rfind("/") b = a[index + 1:] c = b.split("-") if len(c) < n: return "" return c[-n] except Exception: return "Internal error" -
Cargue y registre la UDF.
Cargue el código empaquetado y registre la UDF en DataWorks. Para obtener más información, consulte los siguientes temas:
-
Invoque la UDF.
Una vez registrada la UDF, cree un nodo ODPS SQL para escribir y ejecutar las instrucciones SQL que la invoquen. Para obtener más información sobre los nodos ODPS SQL, consulte Develop an ODPS SQL task. A continuación se muestra un ejemplo de la instrucción SQL.
SET odps.sql.python.version=cp37; -- This command is required to enable Python 3 for the UDF. SELECT UDF_GET_URL_CHAR("http://www.taobao.com/a.htm", 1);
odpscmd
-
Requisitos previos
Descargue e instale odpscmd y luego configure el archivo config para conectarse a un proyecto de MaxCompute. Para obtener más información, consulte Connect by using the MaxCompute client (odpscmd).
-
Escriba el código de la UDF.
Puede desarrollar el código de la UDF en cualquier herramienta de desarrollo de Python y empaquetarlo. A continuación se muestra un ejemplo de código.
from odps.udf import annotate @annotate("string,bigint->string") class GetUrlChar(object): def evaluate(self, url, n): if n == 0: return "" try: index = url.find(".htm") if index < 0: return "" a = url[:index] index = a.rfind("/") b = a[index + 1:] c = b.split("-") if len(c) < n: return "" return c[-n] except Exception: return "Internal error" -
Cargue y registre la UDF.
Cargue el código empaquetado y registre la UDF mediante odpscmd. Para obtener más información, consulte los siguientes temas:
-
Invoque la UDF.
Una vez registrada la UDF, escriba y ejecute una instrucción SQL para invocarla.
SET odps.sql.python.version=cp37; -- This command is required to enable Python 3 for the UDF. SELECT UDF_GET_URL_CHAR("http://www.taobao.com/a.htm", 1);
Instalar la biblioteca NumPy
El entorno de ejecución integrado de Python 3 no incluye NumPy. Si su UDF requiere NumPy, cargue manualmente el paquete WHEEL. Al descargar el paquete desde PyPI o un sitio espejo, el nombre del archivo tiene el formato numpy-<version>-cp37-cp37m-manylinux1_x86_64.whl. Para obtener más información sobre cómo cargar un paquete, consulte Resource operations o Use a third-party package in a Python UDF.
Para consultar la lista de bibliotecas estándar compatibles con Python 3, visite biblioteca estándar de Python 3.
Firmas de función y tipos de datos
Formato de las firmas de función:
@annotate(<signature>)
El parámetro signature es una cadena que especifica los tipos de datos de los parámetros de entrada y del valor de retorno. Al ejecutar una UDF, estos tipos de datos deben coincidir con los especificados en la firma de la función. La validación de coherencia se realiza durante el análisis sintáctico semántico. Si los tipos de datos no coinciden, se devuelve un error. Formato de una firma:
'arg_type_list -> type'
Descripción de los parámetros:
-
arg_type_list: especifica los tipos de datos de los parámetros de entrada. Si se usan varios parámetros de entrada, sus tipos de datos se separan con comas (,). Se admiten los siguientes tipos de datos: BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, DECIMAL, FLOAT, BINARY, DATE, DECIMAL(precision,scale), CHAR y VARCHAR. También son compatibles los tipos de datos complejos, como ARRAY, MAP y STRUCT, así como los tipos de datos complejos anidados.arg_type_listse puede representar con un asterisco (*) o dejar vacío ('').Si
arg_type_listse representa con un asterisco (*), se permite un número variable de parámetros de entrada.Si
arg_type_listse deja vacío (''), no se utilizan parámetros de entrada.
type: especifica el tipo de dato del valor de retorno. Una UDF devuelve únicamente una columna de valores. Se admiten los siguientes tipos de datos: BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, DECIMAL, FLOAT, BINARY, DATE y DECIMAL(precision,scale). También son compatibles los tipos de datos complejos, como ARRAY, MAP y STRUCT, así como los tipos de datos complejos anidados.
Al escribir el código de la UDF, seleccione el tipo de dato según la edición de tipos de datos de MaxCompute que utilice su proyecto. Para obtener más información sobre las ediciones de tipos de datos de MaxCompute y los tipos compatibles con cada una, consulte Data type editions.
La siguiente tabla muestra ejemplos de firmas de función válidas.
|
Firma de la función |
Descripción |
|
|
Los tipos de datos de los parámetros de entrada son BIGINT y DOUBLE, y el tipo de dato del valor de retorno es STRING. |
|
|
Se utiliza un número variable de parámetros de entrada y el tipo de dato del valor de retorno es STRING. |
|
|
No se utilizan parámetros de entrada y el tipo de dato del valor de retorno es DOUBLE. |
|
|
El tipo de dato de los parámetros de entrada es ARRAY<BIGINT> y el tipo de dato del valor de retorno es STRUCT<x:STRING, y:INT>. |
|
|
No se utilizan parámetros de entrada y el tipo de dato del valor de retorno es MAP<BIGINT, STRING>. |
La siguiente tabla describe las asignaciones entre los tipos de datos compatibles con MaxCompute SQL y los tipos de datos de Python 2. Debe escribir las UDF de Python basándose en estas asignaciones para garantizar la coherencia de los tipos de datos.
|
Tipo de MaxCompute SQL |
Tipo de Python 3 |
|
BIGINT |
INT |
|
STRING |
UNICODE |
|
DOUBLE |
FLOAT |
|
BOOLEAN |
BOOL |
|
DATETIME |
DATETIME.DATETIME |
|
FLOAT |
FLOAT |
|
CHAR |
UNICODE |
|
VARCHAR |
UNICODE |
|
BINARY |
BYTES |
|
DATE |
DATETIME.DATE |
|
DECIMAL |
DECIMAL.DECIMAL |
|
ARRAY |
LIST |
|
MAP |
DICT |
|
STRUCT |
COLLECTIONS.NAMEDTUPLE |
Referencia a recursos
Puede hacer referencia a archivos o tablas en el código de UDF de Python 2 mediante el módulo odps.distcache.
-
odps.distcache.get_cache_file(resource_name, mode): devuelve el contenido de un recurso de archivo específico en elmodeindicado.resource_namees una cadena que especifica el nombre de una tabla existente en su proyecto de MaxCompute. Si el nombre de la tabla no es válido o la tabla no existe, se devuelve un error.El parámetro
modees de tipo STRING. Su valor predeterminado es't'. Si establecemodeen't', el archivo se abre en modo texto. Si establecemodeen'b', el archivo se abre en modo binario.El valor de retorno es un objeto similar a un archivo. Si este objeto ya no se utiliza, debe invocar el método
closepara liberar el archivo abierto.
El siguiente código muestra cómo hacer referencia a un archivo.
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): devuelve el contenido de un recurso de tabla específico.El parámetro
resource_nameespecifica un recurso de tabla existente en el proyecto actual de MaxCompute. Se genera una excepción si el nombre del recurso no es válido o si el recurso no existe. Tipos de datos compatibles: BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, FLOAT, CHAR, VARCHAR, BINARY, DATE, DECIMAL, ARRAY, MAP y STRUCT.El valor de retorno es un generador (Generator). Cada iteración produce un registro de la tabla en forma de arreglo.
El siguiente código muestra cómo hacer referencia a una tabla.
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)
Invocación de UDF
Después de desarrollar una UDF de Python 3 siguiendo development workflow, puede invocarla en MaxCompute SQL de la siguiente manera:
Habilitar Python 3
De forma predeterminada, MaxCompute utiliza Python 2. Para usar Python 3, incluya la siguiente marca de sesión en su instrucción SQL.
set odps.sql.python.version=cp37;
Invocar la función
Usar una UDF en un proyecto de MaxCompute: este método es similar al descrito en built-in functions. Puede utilizar una función definida por el usuario de la misma manera que una función integrada.
Usar una UDF entre proyectos: permite utilizar una UDF del Proyecto B dentro del Proyecto A. La siguiente instrucción muestra un ejemplo:
select B:udf_in_other_project(arg0, arg1) as res from table_t;. Para obtener más información sobre cómo compartir recursos entre proyectos, consulte Cross-project resource access based on packages.
Migrar UDF de Python 2
Python 2 llegó a su EOL a principios de 2020. Se recomienda migrar sus proyectos según el tipo de cada uno:
Proyectos nuevos: para los proyectos de MaxCompute recién creados o aquellos en los que escribe UDF de Python por primera vez, utilice Python 3 en todas las UDF.
-
Proyectos existentes: para los proyectos con muchas UDF de Python 2, tenga precaución al habilitar Python 3. Para realizar una migración gradual, utilice los siguientes métodos:
Trabajos y UDF nuevas: use Python 3 para escribir las UDF y habilite Python 3 a nivel de sesión. Para obtener más información sobre cómo habilitar Python 3, consulte Enable Python 3.
-
UDF de Python 2: reescriba las UDF de Python 2 para que sean compatibles tanto con Python 2 como con Python 3. Para obtener más información sobre cómo reescribir las UDF, consulte Porting Python 2 Code to Python 3.
NotaSi escribe UDF públicas que se comparten entre varios proyectos de MaxCompute, asegúrese de que sean compatibles tanto con Python 2 como con Python 3.