暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

如何在 Apache Flink 1.10 中使用 Python UDF?

原创 Spark 2021-12-13
258

简介: 本文将为大家介绍用户如何定义 UDF,并完整展示了如何安装 PyFlink,如何在 PyFlink 中定义/注册/调用 UDF,以及如何执行作业。

75.jpg


镜像下载、域名解析、时间同步请点击 阿里巴巴开源镜像站

一、安装 PyFlink

我们需要先安装 PyFlink,可以通过 PyPI 获得,并且可以使用 pip install 进行便捷安装。
注意: 安装和运行 PyFlink 需要 Python 3.5 或更高版本。

$ python -m pip install apache-Apache Flink

二、定义一个 UDF

除了扩展基类 ScalarFunction 之外,定义 Python UDF 的方法有很多。下面的示例显示了定义 Python UDF 的不同方法,该函数以 BIGINT 类型的两列作为输入参数,并返回它们的和作为结果。

  • Option 1: extending the base class ScalarFunction

  1. class Add(ScalarFunction):


  2. def eval(self, i, j):


  3. return i + j


  4. add = udf(Add(), [DataTypes.BIGINT(), DataTypes.BIGINT()], DataTypes.BIGINT())

  • Option 2: Python function

  1. @udf(input_types=[DataTypes.BIGINT(), DataTypes.BIGINT()], result_type=DataTypes.BIGINT())


  2. def add(i, j):


  3. return i + j

  • Option 3: lambda function
add = udf(lambda i, j: i + j, [DataTypes.BIGINT(), DataTypes.BIGINT()], DataTypes.BIGINT())
  • Option 4: callable function

  1. class CallableAdd(object):


  2. def __call__(self, i, j):


  3. return i + j


  4. add = udf(CallableAdd(), [DataTypes.BIGINT(), DataTypes.BIGINT()], DataTypes.BIGINT())

  • Option 5: partial function

  1. return i + j + k


  2. add = udf(functools.partial(partial_add, k=1), [DataTypes.BIGINT(), DataTypes.BIGINT()],


  3. DataTypes.BIGINT())

三、注册一个UDF

  • register the Python function
table_env.register_function("add", add)
  • Invoke a Python UDF

  1. my_table.select(```js


  2. "add(a, b)")

  • Example Code

下面是一个使用 Python UDF 的完整示例。


  1. from PyFlink.table import StreamTableEnvironment, DataTypes


  2. from PyFlink.table.descriptors import Schema, OldCsv, FileSystem


  3. from PyFlink.table.udf import udf


  4. env = StreamExecutionEnvironment.get_execution_environment()


  5. env.set_parallelism(1)


  6. t_env = StreamTableEnvironment.create(env)


  7. t_env.register_function("add", udf(lambda i, j: i + j, [DataTypes.BIGINT(), DataTypes.BIGINT()], DataTypes.BIGINT()))


  8. t_env.connect(FileSystem().path('/tmp/input')) \


  9. .with_format(OldCsv()


  10. .field('a', DataTypes.BIGINT())


  11. .field('b', DataTypes.BIGINT())) \


  12. .with_schema(Schema()


  13. .field('a', DataTypes.BIGINT())


  14. .field('b', DataTypes.BIGINT())) \


  15. .create_temporary_table('mySource')


  16. t_env.connect(FileSystem().path('/tmp/output')) \


  17. .with_format(OldCsv()


  18. .field('sum', DataTypes.BIGINT())) \


  19. .with_schema(Schema()


  20. .field('sum', DataTypes.BIGINT())) \


  21. .create_temporary_table('mySink')


  22. t_env.from_path('mySource')\


  23. .select("add(a, b)") \


  24. .insert_into('mySink')


  25. t_env.execute("tutorial_job")

  • 提交作业

首先,您需要在“ / tmp / input”文件中准备输入数据。例如,

$ echo "1,2" > /tmp/input

接下来,您可以在命令行上运行此示例:

$ python python_udf_sum.py

通过该命令可在本地小集群中构建并运行 Python Table API 程序。您还可以使用不同的命令行将 Python Table API 程序提交到远程集群。
最后,您可以在命令行上查看执行结果:


  1. $ cat /tmp/output


  2. 3

四、Python UDF 的依赖管理

在许多情况下,您可能希望在 Python UDF 中导入第三方依赖。下面的示例将指导您如何管理依赖项。
假设您想使用 mpmath 来执行上述示例中两数的和。Python UDF 逻辑可能如下:


  1. @udf(input_types=[DataTypes.BIGINT(), DataTypes.BIGINT()], result_type=DataTypes.BIGINT())


  2. def add(i, j):


  3. from mpmath import fadd # add third-party dependency


  4. return int(fadd(1, 2))

要使其在不包含依赖项的工作节点上运行,可以使用以下 API 指定依赖项:


  1. # echo mpmath==1.1.0 > requirements.txt


  2. # pip download -d cached_dir -r requirements.txt --no-binary :all:


  3. t_env.set_python_requirements("/path/of/requirements.txt", "/path/of/cached_dir")

用户需要提供一个 requirements.txt 文件,并且在里面申明使用的第三方依赖。如果无法在群集中安装依赖项(网络问题),则可以使用参数“requirements_cached_dir”,指定包含这些依赖项的安装包的目录,如上面的示例所示。依赖项将上传到群集并脱机安装。
下面是一个使用依赖管理的完整示例:


  1. from PyFlink.datastream import StreamExecutionEnvironment


  2. from PyFlink.table import StreamTableEnvironment, DataTypes


  3. from PyFlink.table.descriptors import Schema, OldCsv, FileSystem


  4. from PyFlink.table.udf import udf


  5. env = StreamExecutionEnvironment.get_execution_environment()


  6. env.set_parallelism(1)


  7. t_env = StreamTableEnvironment.create(env)


  8. @udf(input_types=[DataTypes.BIGINT(), DataTypes.BIGINT()], result_type=DataTypes.BIGINT())


  9. def add(i, j):


  10. from mpmath import fadd


  11. return int(fadd(1, 2))


  12. t_env.set_python_requirements("/tmp/requirements.txt", "/tmp/cached_dir")


  13. t_env.register_function("add", add)


  14. t_env.connect(FileSystem().path('/tmp/input')) \


  15. .with_format(OldCsv()


  16. .field('a', DataTypes.BIGINT())


  17. .field('b', DataTypes.BIGINT())) \


  18. .with_schema(Schema()


  19. .field('a', DataTypes.BIGINT())


  20. .field('b', DataTypes.BIGINT())) \


  21. .create_temporary_table('mySource')


  22. t_env.connect(FileSystem().path('/tmp/output')) \


  23. .with_format(OldCsv()


  24. .field('sum', DataTypes.BIGINT())) \


  25. .with_schema(Schema()


  26. .field('sum', DataTypes.BIGINT())) \


  27. .create_temporary_table('mySink')


  28. t_env.from_path('mySource')\


  29. .select("add(a, b)") \


  30. .insert_into('mySink')


  31. t_env.execute("tutorial_job")

  • 提交作业

首先,您需要在“/ tmp / input”文件中准备输入数据。例如,


  1. echo "1,2" > /tmp/input


  2. 1


  3. 2

其次,您可以准备依赖项需求文件和缓存目录:


  1. $ echo "mpmath==1.1.0" > /tmp/requirements.txt


  2. $ pip download -d /tmp/cached_dir -r /tmp/requirements.txt --no-binary :all:

接下来,您可以在命令行上运行此示例:

$ python python_udf_sum.py

最后,您可以在命令行上查看执行结果:


  1. $ cat /tmp/output


  2. 3

五、快速上手

PyFlink 为大家提供了一种非常方便的开发体验方式 - PyFlink Shell。当成功执行 python -m pip install apache-flink 之后,你可以直接以 pyflink-shell.sh local 来启动一个 PyFlink Shell 进行开发体验,如下所示:

1.gif

六、更多场景

不仅仅是简单的 ETL 场景支持,PyFlink 可以完成很多复杂场的业务场景需求,比如我们最熟悉的双 11 大屏的场景,如下:

2.jpg



关于上面示例的更多详细请查阅:https://enjoyment.cool/2019/12/05/Apache-Flink-说道系列-如何在PyFlink-1-10中自定义Python-UDF/

本文转自: 如何在 Apache Flink 1.10 中使用 Python UDF?-阿里云开发者社区


「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论