Python实现MaxCompute UDF/UDAF/UDTF

MaxCompute的UDF包括:UDF,UDAF和UDTF三种函数,本文将重点介绍如何通过Python实现这三种函数。

参数与返回值类型

参数与返回值通过如下方式指定:

PythonUDF目前支持ODPSSQL数据类型有:bigint,string,double,boolean和datetime。SQL语句在执行之前,所有函数的参数类型和返回值类型必须确定。因此对于Python这一动态类型语言,需要通过对UDF类加decorator的方式指定函数签名。

函数签名signature通过字符串指定,语法如下:

arg_type_list'->'type_list

arg_type_list:type_list|'*'|''

type_list:[type_list',']type

type:'bigint'|'string'|'double'|'boolean'|'datetime'

·箭头左边表示参数类型,右边表示返回值类型。

·只有UDTF的返回值可以是多列,UDF和UDAF只能返回一列。

·‘*’代表变长参数,使用变长参数,UDF/UDTF/UDAF可以匹配任意输入参数。

下面是合法的signature的例子:

'bigint,double->string'#参数为bigint、double,返回值为string

'bigint,boolean->string,datetime'#UDTF参数为bigint、boolean,返回值为string,datetime

'*->string'#变长参数,输入参数任意,返回值为string

'->double'#参数为空,返回值为double

Query语义解析阶段会将检查到不符合函数签名的用法,抛出错误禁止执行。执行期,UDF函数的参数会以函数签名指定的类型传给用户。用户的返回值类型也要与函数签名指定的类型一致,否则检查到类型不匹配时也会报错。ODPSSQL数据类型对应Python类型如下:

注解:

·Datetime类型是以int的形式传给用户代码的,值为epochutctime起始至今的毫秒数。用户可以通过Python标准库中的datetime模块处理日期时间类型。

·NULL值对应Python里的None。

UDF

实现PythonUDF非常简单,只需要定义一个new-styleclass,并实现evaluate方法。下面是一个例子:

注解:PythonUDF必须通过annotate指定函数签名。

UDAF

·classodps.udf.BaseUDAF:继承此类实现PythonUDAF。

·BaseUDAF.new_buffer():实现此方法返回聚合函数的中间值的buffer。buffer必须是mutableobject(比如list,dict),并且buffer的大小不应该随数据量递增,在极限情况下,buffermarshal过后的大小不应该超过2Mb。

·BaseUDAF.iterate(buffer[,args,...]):实现此方法将args聚合到中间值buffer中。

·BaseUDAF.merge(buffer,pbuffer):实现此方法将两个中间值buffer聚合到一起,即将pbuffermerge到buffer中。

·BaseUDAF.terminate(buffer):实现此方法将中间值buffer转换为ODPSSQL基本类型。

下面是一个UDAF求平均值的例子。

UDTF

·classodps.udf.BaseUDTF:PythonUDTF的基类,用户继承此类,并实现process,close等方法。

·BaseUDTF.init():初始化方法,继承类如果实现这个方法,则必须在一开始调用基类的初始化方法super(BaseUDTF,self).init()。init方法在整个UDTF生命周期中只会被调用一次,即在处理第一条记录之前。当UDTF需要保存内部状态时,可以在这个方法中初始化所有状态。

·BaseUDTF.process([args,...]):这个方法由ODPSSQL框架调用,SQL中每一条记录都会对应调用一次process,process的参数为SQL语句中指定的UDTF输入参数。

·BaseUDTF.forward([args,...]):UDTF的输出方法,此方法由用户代码调用。每调用一次forward,就会输出一条记录。forward的参数为SQL语句中指定的UDTF的输出参数。

·BaseUDTF.close():UDTF的结束方法,此方法由ODPSSQL框架调用,并且只会被调用一次,即在处理完最后一条记录之后。

下面是一个UDTF的例子。

注解:PythonUDTF也可以不加annotate指定参数类型和返回值类型。这样,函数在SQL中使用时可以匹配任意输入参数,但返回值类型无法推导,所有输出参数都将认为是string类型。因此在调用forward时,就必须将所有输出值转成str类型。

引用资源

PythonUDF可以通过odps.distcache模块引用资源文件,目前支持引用文件资源和表资源。

o返回指定名字的资源内容。resource_name为str类型,对应当前Project中已存在的资源名。如果资源名非法或者没有相应的资源,会抛出异常。

o返回值为file-likeobject,在使用完这个object后,调用者有义务调用close方法释放打开的资源文件。

下面是使用get_cache_file的例子:

o返回指定资源表的内容。resource_name为str类型,对应当前Project中已存在的资源表名。如果资源名非法或者没有相应的资源,会抛出异常。

o返回值为generator类型,调用者通过遍历获取表的内容,每次遍历得到的是以tuple形式存在的表中的一条记录。

下面是使用get_cache_table的例子:

更多Python语言测试,请前往51Testing软件测试网。

本文来自企鹅号 - 51软件测试网媒体

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java一日一条

教你在Java接口中定义方法

基本上所有的Java教程都会告诉我们Java接口的方法都是public、abstract类型的,没有方法体的。

911
来自专栏阮一峰的网络日志

如何判断Javascript对象是否存在

Javascript语言的设计不够严谨,很多地方一不小心就会出错。 举例来说,请考虑以下情况。 现在,我们要判断一个全局对象myObj是否存在,如果不存在,就对...

36311
来自专栏积累沉淀

JDK动态代理的底层实现原理

JDK动态代理的底层实现原理      动态代理是许多框架底层实现的基础,比如Spirng的AOP等,其实弄清楚了动态代理的实现原理,它就没那么神奇了,下面就来...

5907
来自专栏Vamei实验室

Python标准库05 存储对象 (pickle包,cPickle包)

在之前对Python对象的介绍中 (面向对象的基本概念,面向对象的进一步拓展),我提到过Python“一切皆对象”的哲学,在Python中,无论是变量还是函数,...

2059
来自专栏PHP在线

PHP5 的对象赋值机制介绍

看到PHP设计模式中值对象模式中的例题,对于结果总感到有点疑惑。回头看了下PHP5的对象赋值才真正清楚。 复制代码 代码如下: <?php class Si...

2867
来自专栏mukekeheart的iOS之旅

Java程序员面试宝典——重要习题整理

1、下面程序的输出结果是() public class Test { public static void main(String[] arg...

2409
来自专栏崔庆才的专栏

Python 3 中 Redis 的用法

在本节我们介绍一下 Python 的 Redis 操作,在本节开始之前请确保你已经安装好了 Redis 及Python Redis 库。Redis 库提供两个类...

1.9K1
来自专栏友弟技术工作室

Go 程序的基本结构和要素

示例 package main import "fmt" func main() { fmt.Println("hello, world") } 包...

33111
来自专栏高性能服务器开发

Linux内核中的printf实现

参数中明显采用了可变参数的定义,而在main.c函数的后面直接调用了printf函数,我们可以看下printf函数的参数是如何使用的。

1162
来自专栏java一日一条

教你在Java接口中定义方法

接下来,SimpleTimeClient类实现了TimeClient接口,具体代码如下:

1212

扫码关注云+社区

领取腾讯云代金券