阿里云 Maxcompute Python UDF

UDF基本概念

  1. udf
    一条输入对应一条输出。
select concat('a','b') from cid_dd
// 结果 ab
  1. UDTF
    一条输入对应着多条输出
select bi_udtf:split_rows("a,b") from cid_dd
// 结果: a
//       b 
  1. UDAF:
    多条输入对应一条输出
select wm_concat(col, ',') from cid_dd
// 结果 a,b

限制

环境限制

MaxCompute UDF的python版本为2.7,并以沙箱模式执行用户代码,即代码是在一个受限的运行环境中执行的。以下行为是被禁止的

  • 读写本地文件
  • 启动子进程
  • 启动线程
  • 使用Socket通信
  • 其他系统的调用
参数和返回值类型

参数和返回值指定方式如下:

@odps.udf.annotate(signature)

Python UDF 目前支持的数据类型包含 bigint, string, double, boolean, datetime。sql语句在执行之前,必须确认所有函数的参数类型和返回值类型。因此对于python动态类型语言,需要通过对UDF类加上Decorator方式指定函数签名。
合法的Signature示例如下:

'bigint,double->string'            # 参数为bigint、double,返回值为string。
'bigint,boolean->string,datetime'  # UDTF参数为bigint、boolean,返回值为string,datetime。
'*->string'                        # 变长参数,输入参数任意,返回值为string。
'->double'                         # 参数为空,返回值为double。

MaxCompute SQL数据类型对应的Python类型如下


image.png

UDF 开发

实现Python UDF非常简单,只需要定义一个 new-style class,并实现evaluate方法

from odps.udf import annotate
# 标记输入的参数类型
@annotate("string->string")
class Hello(object):

    def evaluate(self, arg0):
        return arg0 + 'Hello'

如何调试和查看输出

Hello("dankun_")
// 结果 dankun_Hello

UDTF

from odps.udf import annotate
from odps.udf import BaseUDTF
@annotate('string -> string')
class Explode(BaseUDTF):
   """将string按逗号分隔输出成多条记录。
   def process(self, arg):
       props = arg.split(',')
       for p in props:
           self.forward(p)
  • class odps.udf.BaseUDTF: Python UDTF 的基类,实现process,close等方法
  • BaseUDTF.init(): 初始化方法。继承类如果需要实现这个方法,必须在一开始调用基类的初始化方法super(BaseUDTF, self).__init__()。init方法在整个UDTF生命周期中只会被调用一次,即在处理第一条记录之前。当UDTF需要保存内部状态时,可以在这个方法中初始化所有状态
  • BaseUDTF.process([args, ...]),这个方法由框架调用,SQL中每一条记录都会对应调用一次process,process的参数为SQL语句中指定的UDTF输入参数
  • BaseUDTF.forward([args, ...]): UDTF的输出方法(类似于return ),由用户代码调用。每调用一次forward,便会输出一条记录。forward的参数为SQL语句中指定的UDTF的输出参数
  • BaseUDTF.close(): UDTF的结束方法。此方法由MaxCompute SQL框架调用,并且只会被调用一次,即在处理完最后一条记录之后。

UDAF

from odps.udf import annotate
from odps.udf import BaseUDAF

@annotate('double->double')
class Average(BaseUDAF):
    def new_buffer(self):
        return [0, 0]
    def iterate(self, buffer, number):
        if number is not None:
            buffer[0] += number
            buffer[1] += 1
    def merge(self, buffer, pbuffer):
        buffer[0] += pbuffer[0]
        buffer[1] += pbuffer[1]
    def terminate(self, buffer):
        if buffer[1] == 0:
            return 0.0
        return buffer[0] / buffer[1]
  • class odps.udf.BaseUDAF:继承此类实现Python UDAF。
  • BaseUDAF.new_buffer():实现此方法返回聚合函数的中间值的bufferbuffer必须是marshallableObject(例如LIST、DICT),并且buffer的大小不应该随数据量递增。在极限情况下,bufferMarshal过后的大小不应该超过2MB。
  • BaseUDAF.iterate(buffer[, args, ...]):实现此方法将args聚合到中间值buffer中。
  • BaseUDAF.merge(buffer, pbuffer):实现此方法将两个中间值buffer聚合到一起,即将pbuffer合并到buffer中。
  • BaseUDAF.terminate(buffer):实现此方法将中间值buffer转换为MaxCompute SQL的基本类型。

你可能感兴趣的:(阿里云 Maxcompute Python UDF)