【MaxCompute 常见问题】 UDF

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
云原生大数据计算服务 MaxCompute,5000CU*H 100GB 3个月
云原生大数据计算服务MaxCompute,500CU*H 100GB 3个月
简介: 查看资源信息假设资源名称为 pyudf_test.py,在 odpscmd 客户端执行 desc resource pyudf_test.py;,或在 datastudio 中新建 SQL 节点后输入 desc resource pyudf_test.py;执行。

UDF


使用 MaxCompute UDF 过程中常见报错问题


1. 查看 UDF 函数信息

假设UDF 函数名称为 example_function,在odpscmd 客户端执行 desc function example_funct ion;,或在 datastudio 中新建 SQL 节点后输入 desc function example_function;执行。可以得到输出示例如下:


Name

example_function

Owner

xxxx

Created Time

2021-03-13 22:52:28

Class

pyudf_test.SampleUDF

Resources

pyudf_test.py, numpy.zip, table_resource_example

输出各项的含义:

  • Created TimeUDF 函数在MaxCompute 中注册的时间
  • Class:声明 UDF “Python脚本名.类名,区分大小写
  • ResourcesUDF 函数依赖的资源列表,依赖的三方包和表资源也需要在资源列表里(例如上面的 numpy.zip table_resource_example


需要注意的是:类名(Class)里的 Python 脚本名为 底层唯一标识的资源名 。MaxCompute 的资源名大小写不敏感,如果第一次上传资源时资源名为 pyudf_test.py,后面在 datastudio 重命名资源、或者用 odpscmd 覆盖资源时将资源名重命名为 PYUDF_TEST.py,此时 底层唯一标识的资源名 仍然为 pyudf_test.py,因此注册 UDF 函数时,类名仍然需要填 pyudf_test.SampleUDFod pscmd 可以通过 list resource; 命令查看所有资源 底层唯一标识的资源名。


2. 查看资源信息

假设资源名称为 pyudf_test.py,在 odpscmd 客户端执行 desc resource pyudf_test.py;,或在 datastudio 中新建 SQL 节点后输入 desc resource pyudf_test.py;执行。可以得到输出示例如下:


Name

pyudf_test.py

Owner

xxx

Type

PY

Comment

xxx

CreatedTime

2021-03-13 22:52:28

LastModifiedTime

2021-03-13 22:52:28

LastUpdator

Size

155

Md5sum

62f3e01697db19c6e318dde67e6e9626


输出各项的含义:

  • Type:资源类型
  • CreatedTime:资源创建时间
  • LastModifiedTime:资源最后更新时间 l Md5sum:资源文件的 md5


需要注意的是:因为 MacCompute 的资源名大小写不敏感,resource_A resource_a 是同一资源,上面 “Name” 项的输出和 desc resource <resource_name>; 里输入的<resource_name>大小写一致。


3. 性能问题

1 kInstanceMonitorTimeout, usually caused by bad udf performance

报错原因:默认情况下 UDF 处理 1024 条输入数据的总时长超过 1800 秒报错。

排查方法:

  • UDF 中加一些日志,检查 UDF 是否有死循环,处理特定数值的耗时是否有异常,UDF 里打印日志的方法参考后文中的打印日志部分。
  • UDF 数据处理逻辑的头尾打印日志,预估 UDF 的执行时间。


解决方法:

  • 修复 UDF 中存在的死循环等问题。
  • 如果 UDF 预计的运行时间本身就很长,可以通过调整以下两个参数避免超时报错,设置这两个参数后,UDF 处理 x 条输入数据,超过 y 秒则超时报错。
  • set odps.sql.executionengine.batch.rowcount=x;
  • set odps.sql.udf.timeout=y; y 最大值为 3600


4. 线上 UDF 性能比单机测试性能差很多


2 function or view 'xxx' cannot be resolved

  • 确认使用 UDF 函数的项目和注册 UDF 函数的项目一致,请注意分辨是生产还是开发项目。
  • 进入使用 UDF 函数的项目
  • 查看 UDF 函数信息
  • 检查输出结果中“Class”是否正确,如果不对,需要重新注册函数。示例中 pyudf_test python文件 pyudf_test.py 的名字,SampleUDF pyudf_test.py 中定义 UDF 函数的类名(注意区分大小写)。
  • 检查输出结果中“Resources”是否正确、完整,如果不对,需要重新注册函数。UDF 里如果需要引用文件资源(get_cache_file)、表资源(get_cache_table)、压缩包资源(get_cache_archive)、第三方包,注册函数时要将这些资源填到资源列表里。
  • 查看资源信息,检查输出结果中资源的类型“Type”和更新时间“LastModifiedTime”是否正确:
  • get_cache_file 使用的文件资源类型为 FILE
  • get_cache_table 使用的表资源类型是 TABLE
  • get_cache_archive 或三方包的资源类型是 ARCHIVE

确认是否已将 datastudio 中的资源正确同步到 MaxCompute,如果 3.b 输出的 LastModifiedTime 不是最新的,可能是资源从datastudio 同步到 MaxCompute 有延迟,资源还没更新。


  • 确认使用的是 Python2 还是 Python3 UDF
  • 如果没有项目级别打开 Python3 UDF,作业默认会使用 Python2 UDF,此时 Python 文件中如果有非 ASCII 编码字符,会报错:SyntaxError: Non-ASCII charactor '\xe8' in file xxx. online yyy.
  • 如果要使用 Python3 UDF,需要在 SQL 语句前加上 set odps.sql.python.version=cp37; 文档参考 Python3UDF


3 IOError: Download resource: xxx.zip failed, Perhaps you forgot to add it to using list when create funciton odps.distcache.DistributedCacheError: Invalid relative path, file not exists uxi job failed, caused by: Download resource failed:

xxx.zip 场景:Python UDF 里使用 get_cache_archive('xxx.zip')时报错。


排查步骤:

  • 查看 UDF 函数信息(desc function your_udf_function;)确认输出的“Resources”里是否有 xxx.zip
  • 查看资源信息(desc re 链接 source xxx.zip;)确认输出的“Type”是否是 ARCHIVE
  • 确认资源名字和实际文件格式一致。如果资源名字为 xxx.zip,但实际上传的文件是 xxx.tar.gz,此时会按 zip 格式解压,会解压失败报错。
  • 解决方法:上传 xxx.zip ARCHIVE 类型资源,注册函数时资源列表里要加上 xxx.zip
  • get_cache_archive 使用方法参考


4 odps.distcache.DistributedCacheError: Table resource "xxx_table_name" not found. You should declare to use it when creating your function. 场景:Python UDF 里使用 get_cache_table(xxx_table_name)时报错。

排查步骤:

  • 查看 UDF 函数信息(desc function your_udf_function;)确认输出的“Resources”里是否有 xxx_table_name
  • 查看资源信息(desc resource xxx_table_name;)确认输出的“Type”是否是 TABLE

解决方法:上传xxx_table_name TABLE 类型资源,注册函数时资源列表里要加上 xxx_table_name get_cache_table 使用方法参考


5 ImportError: No module named 'xxx'

找不到三方包时:

  • 查看资源信息(desc resource resource-of-xxx.zip;) 检查三方包是否已上传为 MaxCompute ARCHIVE 类型资源,检查资源信息里的 TypeLastModifiedTimeMd5sum 是否符合预期。
  • 查看 UDF 函数信息,检查注册函数时类名填写是否正确、三方包资源是否已填到资源列表里。
  • 检查 UDF 代码里是否将三方包的路径加到 system path 中。
  • 假设模块名为 xxx 时,需要确定文件夹 xxx 或文件 xxx.py 所在路径。

UDF 里把这个路径加到 system path 中。

  • 确定文件所在路径的方法:


如果将文件夹resource_dir 直接压缩为 resource-of-xxx.zip。那么 UDF 运行时文件夹

resource_dir 所在路径为work/resource-of-xxx.zip/resource_dir/ 如果选择文件夹resource_dir 内所有文件压缩为 resource-of-xxx.zip(即不包含 resource_ dir)。那么 UDF 运行时 resource_dir 里的某个文件比如 xxx.py 所在路径为 work/resour

ce-of-xxx.zip/resource-of-xxx.zip 在本地解压后,假设 xxx 模块所在文件的相对路径为 path1/path2/xxx.p y、或 xxx 模块文件夹的相对路径为 path1/path2/xxx。则需要在 UDF 代码添加如:sys.path. insert(0, 'work/resource-of-xxx.zip/path1/path2')。(ARCHIVE 资源默认放在 UDF 执行路径的相对路径 ./work/中)


  • 三方包如果是 whl 包,请检查 whl 包的后缀是否正确,python2 要求名字包含“cp27-cp27m-manylinux1_x86_64”python3要求名字包含“cp37-cp37m-manylinux1_x86_64”whl 文件直接改后缀为 zip,不要对 whl 文件再次打包生成 zip 文件。
  • 三方包如果不是 whl 包,但是是纯 python 包,请参考第 3 步检查压缩包的目录结构,需要将 x xx 文件夹或 xxx.py 的上层目录路径加到 sys.path 中。
  • 三方包如果不是 whl 包,也不是纯 python 包,检查里面是否有 setup.py,如果有 setup.py,需要在兼容环境编译后再重新上传使用,编译方法参考
  • 检查 UDF 文件名和要引用的三方包模块名是否冲突。如果 UDF 文件是 xxx.pyimport xxx 时默认会导入 xxx.py 而不是三方包里的模块,此时需要修改 UDF 文件名。
  • 检查报错的 import 语句是否写在 UDF 所在类的外部。如果是,需要移到 UDF 所在类内部 import。因为语法检查阶段不会下载三方包,即使尝试将三方包路径加到了 sys path 中,编译检查时也会报错 ImportError


6 Python3标准库 ImportError Python3.7标准库列


7 ImportError: No module named enum ImportError: No module named request

如果没有项目级别打开Python3 UDF,作业默认会使用 Python2 UDF,不包含 Python3 的一些标准库如 enumurllib.request 等。

如果要使用 Python3 UDF,需要在 SQL 语句前加上 setodps.sql.python.version=cp37;,文档参考 Python3UDF


8 SyntaxError: Non-ASCII charactor '\xe8' in file xxx. on line yyy

报错原因:作业使用 Python2 UDF,且 Python 文件中如果有非 ASCII 编码字符。

解决方法:

  • SQL 语句前加上 set odps.sql.python.version=cp37;使用 Python3 UDF,文档参考 Python3 UDF
  • Python2 的默认编码方式修改为 UTF-8,即在 Python 文件开头加上如下语句:

import sys reload(sys) sys.setdefaultencoding('utf-8')


9  UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position x-y: ordinal not in range(128)

报错原因:使用 Python2 UDF 时,annotate 中返回值类型是 stringUDF 里返回了一个unicode 类型的 Python Object(假设是ret)。此时默认会返回 str(ret),对 ret 使用 ascii 编码。

解决方法:UDF unicode 转为 str 后再输出,例如 returnret.encode('utf-8')


10 UnicodeDecodeError: 'utf-8' codec can't decode byte xxx in position xxx: invalid continuation byte

报错原因:使用 Python3 UDF 时,annotate 中输入参数类型是 string,但是输入的 odps string 不能按 utf-8 解码为 str 类型的 Python Object

解决方法:

  • 避免向 odps 表写入非 utf-8 编码的字符串。例如:

Python2 UDF 返回的 Python Object 是按 gbk 编码的 str,可以被正常写入 odps 表,但无法被 Python3 UDF 读出,建议返回 ret.decode('gbk').encode('utf-8')

  • SQL 中用内置函数 is_encoding 提前过滤掉非 utf-8 编码的数据。例如:

select py_udf(input_col) from example_tablewhere is_encoding(input_col, 'utf-8', 'utf-8') = true;

  • annotate 中输入参数的类型改成 binary,改写 SQL string 列转为binary 列再输入到 UDF 中。此时 UDF 中输入的 Python Object bytes。例如:

select py_udf(cast(input_col as binary)) from example_table;

  • resolve annotation of class xxx for UDTF yyy contains invalid content

'<EOF>', please check format and type 可能原因:UDF/UDTF/UDAF 输入或输出为复杂类型时,annotate 里的函数签名不合法。


合法的函数签名请参考Python3UDF-参数与返回值,需要特别注意array/map/struct 等复杂类型的写法。


12 Script exception - ValueError: unmarshallable object

报错原因:Python UDAF 声明 buffer 里的元素不是 marshal对象,常见于使用复杂类型 buffer 时。解决方法:

  • buffer 里的元素赋值时,要检查赋的值是否是 marshal 对象。
  • 假设 UDAF 里要使用两个 buffer,类型分别为 list dict,那么new_buffer 方法里应该return [list(), dict()]iterate/merge/terminate 方法里使用 buffer/pbuffer时,list 类型的 buffer 对应 buffer[0]/pbuffer[0]dict 类型的 buffer 对应 buffer[1]/pbuffer[1]
  • 如果 buffer 里的元素是 list dictlist 里的元素、dict key/value 也必须是 marshal对象。


13 TypeError: expected <class 'xxx'> but <class 'yyy'> found, value:zzz

报错原因:Python UDF 返回的 python 数据类型(yyy)与odps 期望的 python 数据类型(xxx)不一致。

解决方法:请检查UDF annotate里写的返回值类型和Python代码里实际返回的数据类型是否匹配。


14 Semantic analysis exception - expect xxx aliases but have 0

SQL 语句中调用 UDTF 函数时写法错误,例如 UDTF 函数名为 my_udtf,输入 2 列,输出 3列,正确的写法为:

select my_udtf(col0, col1) as (ret_col0, ret_col1, ret_col2) from tmp1;


15 Semantic analysis exception - evaluate function in class xxx.yyy for user defined function zz does not match annotation ***->***

报错原因:annotate里声明的输入参数个数与 Python UDF/UDTF/UDAF evaluate/process/ iterate 方法的入参个数不一致。


16 Semantic analysis exception - failed to get Udf info from xxx.py

报错原因 1:加载 UDTF/UDAF 基类的写法不对,比如写成了 import odps.udf.BaseUDTF import odps.udf.BaseUDAF

解决方法 1:修改为 from odps.udf import BaseUDTF from odps.udf import BaseUDTF


报错原因 2UDF 所在类外面有 import 三方包的语句。因为语法检查阶段不会下载三方包,即使尝试将三方包路径加到了 sys path 中,编译检查时也会报错无法 import。解决方法 2:将 import 三方包的语句改写到 UDF 类内部。


17 Semantic analysis exception - download resource xxx.py failed, detail message: ODPS-0020011:Invalid parameter - Resource conflict for name xxx.py the candicate projects are project_a and project_b

报错原因:同一个作业中有两个UDF 依赖了不同 project 下的同名资源。

解决方法:

  • 排查作业依赖的所有 UDF(包括视图中依赖的 UDF),检查 UDF 所属 project 和对应资源的名称。
  • 修改依赖的 UDF 或资源名称,避免依赖不同 project 下的同名资源。


18 RuntimeError: xxx has been blocked by sandbox

报错原因:用户 Python2 UDF 内的某些函数调用被沙箱阻断了。

解决方法:

  • SQL 语句前设置参数 set odps.isolation.session.enable=true; (区分大小写)。
  • 使用 Python3 UDF,会默认设置上 set odps.isolation.session.enable=true;


19 Python UDAF buffer size overflowed: 2821486749

报错原因:Python UDAF 中的 buffer marshal 过后的大小超过2GB,用户使用 buffer 的方式有误,buffer 的大小不应该随数据量递增。

解决方法:重新设计 UDAF 的逻辑,buffer 的大小不应该随数据量递增。例如声明了一个 buffer listiterate merge 阶段不能一直往 buffer append 数据。

image.png


20 GLIBCXX_3.4.21 not foundGLIBCCXXABI 同理)

报错原因:报错的 so 文件依赖的 GLIBCXX 版本高于 odps 本身的 GLIBCXX 版本。解决方法:报错一般出现在用户引入的三方包内的so,用户编译该 so 使用的 gcc 版本比 ODPS 兼容的gcc 版本高,需要使用兼容的 wheel 包、或者在兼容的环境中重新编译 so。附:ODPS 支持的二进制可执行文件或 so 文件依赖的最大版本:

GLIBC <= 2.17

CXXABI <= 1.3.8

GLIBCXX <= 3.4.19

GCC <= 4.2.0


21 libprotobuf FATAL

相关报错信息在 StdErr 中出现,报错原因一般是用户三方包内依赖的 protobuf 库和 ODPS 本身依赖的 protobuf 库版本不兼容。


22 pytorch报错 process killed by signal 6

目前已知使用 1.3.11.4.0 版本的pytorch 会报错,使用 1.5.0 版本没有问题。


23 OpenCV报错ImportError: libGL.so.1: cannot open shared object file: No such file or directory


5. 打印日志

  • Python2

sys.stdout.write('your log') sys.stdout.flush()

  • Python3

print('your log', flush=True)


执行时日志将输出到 logview stdout 中:

image.png


6. 常用文档链接

  • 添加资源:
  • 注册函数
  • UDF 读取 MaxCompute 文件资源、表资源示例
  • DF 使用第三方包示例


>>快来点击免费下载《阿里云MaxCompute百问百答》了解更多详情!<<


相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
SaaS 模式云数据仓库必修课
本课程由阿里云开发者社区和阿里云大数据团队共同出品,是SaaS模式云原生数据仓库领导者MaxCompute核心课程。本课程由阿里云资深产品和技术专家们从概念到方法,从场景到实践,体系化的将阿里巴巴飞天大数据平台10多年的经过验证的方法与实践深入浅出的讲给开发者们。帮助大数据开发者快速了解并掌握SaaS模式的云原生的数据仓库,助力开发者学习了解先进的技术栈,并能在实际业务中敏捷的进行大数据分析,赋能企业业务。 通过本课程可以了解SaaS模式云原生数据仓库领导者MaxCompute核心功能及典型适用场景,可应用MaxCompute实现数仓搭建,快速进行大数据分析。适合大数据工程师、大数据分析师 大量数据需要处理、存储和管理,需要搭建数据仓库?学它! 没有足够人员和经验来运维大数据平台,不想自建IDC买机器,需要免运维的大数据平台?会SQL就等于会大数据?学它! 想知道大数据用得对不对,想用更少的钱得到持续演进的数仓能力?获得极致弹性的计算资源和更好的性能,以及持续保护数据安全的生产环境?学它! 想要获得灵活的分析能力,快速洞察数据规律特征?想要兼得数据湖的灵活性与数据仓库的成长性?学它! 出品人:阿里云大数据产品及研发团队专家 产品 MaxCompute 官网 https://www.aliyun.com/product/odps&nbsp;
相关文章
|
9天前
|
分布式计算 大数据 调度
MaxCompute产品使用问题之为什么用python写的udf函数跑起来比本地还要慢
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
9天前
|
机器学习/深度学习 分布式计算 DataWorks
MaxCompute产品使用问题之如何在UDF函数中访问外网
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
9天前
|
SQL 分布式计算 大数据
MaxCompute产品使用问题之建了一个python 的 UDF脚本,生成函数引用总是说类不存在,是什么导致的
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
9天前
|
JSON 分布式计算 大数据
MaxCompute产品使用问题之pyODPS3如何引用udf资源的函数
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
9天前
|
分布式计算 大数据 调度
MaxCompute产品使用问题之如何解决UDF针对数据每行操作,而XGBoost需要对数据整体操作的问题
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
9天前
|
SQL 分布式计算 MaxCompute
MaxCompute操作报错合集之通过UDF(用户定义函数)请求外部数据库资源并遇到报错,是什么原因
MaxCompute是阿里云提供的大规模离线数据处理服务,用于大数据分析、挖掘和报表生成等场景。在使用MaxCompute进行数据处理时,可能会遇到各种操作报错。以下是一些常见的MaxCompute操作报错及其可能的原因与解决措施的合集。
|
9天前
|
机器学习/深度学习 分布式计算 DataWorks
MaxCompute产品使用问题之在dataworks中,如何查看所有的udf和resouce列表
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
22天前
|
存储 分布式计算 大数据
MaxCompute操作报错合集之通过UDF调用异常(其他使用http调用正常)。报错:java.lang.NoSuchMethodError:是什么导致的
MaxCompute是阿里云提供的大规模离线数据处理服务,用于大数据分析、挖掘和报表生成等场景。在使用MaxCompute进行数据处理时,可能会遇到各种操作报错。以下是一些常见的MaxCompute操作报错及其可能的原因与解决措施的合集。
|
22天前
|
存储 分布式计算 大数据
MaxCompute操作报错合集之自定义udf的函数,引用了import net.sourceforge.pinyin4j.PinyinHelper;但是上传资源后,出现报错,是什么原因
MaxCompute是阿里云提供的大规模离线数据处理服务,用于大数据分析、挖掘和报表生成等场景。在使用MaxCompute进行数据处理时,可能会遇到各种操作报错。以下是一些常见的MaxCompute操作报错及其可能的原因与解决措施的合集。
|
22天前
|
存储 分布式计算 大数据
MaxCompute产品使用合集之在sql里调用自定义的udf时,设置一次同时处理的数据行数,是并行执行还是串行执行的
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。