PIG UDF (Python) 字符集编码

Posted

技术标签:

【中文标题】PIG UDF (Python) 字符集编码【英文标题】:PIG UDF (Python) Charset Encoding 【发布时间】:2015-02-23 16:30:13 【问题描述】:

我是编写 Python 和 Pig UDF 的初学者,并且正在努力使用 PIG 对输入文件进行字符集转换。

浏览***和整个互联网几天,尝试了很多不同的东西,但我仍然无助。

希望有人可以轻轻推动我朝着正确的方向前进。


环境:真正的分布式 Hadoop 集群(无本地实例)/Cloudera 配置有utf-8Apache Pig version 0.12.0

我的源文件使用iso-8859-1 编码,目标是将其内容存储为utf-8(在pig 中的其他几个操作之后或之前)。

输入文件如下所示(几个 ASCII/iso-8859-1 字符用于测试目的 - 每行一个字符):

ù
û
ü
ÿ
à
â
æ
ç
é
è
ê
ë
î
ô

这是我的猪脚本:

RMF $output;

REGISTER 'charsetConversion.py' using org.apache.pig.scripting.jython.JythonScriptEngine AS pyudf;

data = LOAD '$input' USING PigStorage() AS (col1:chararray); --col1:bytearray

final = foreach data generate $0, pyudf.toUTF8(col1);

STORE final INTO '$output' USING PigStorage();

还有我的UDF(用python写的):

#!/usr/bin/env python
# charsetConversion.py

@outputSchema("word:chararray")
def toUTF8(s):
    return unicode(s, 'iso-8859-1').encode('utf-8')

运行/提交脚本后,我得到以下输出:

�	�
�	�
�	�
�	�
�	�
�	�
�	�
�	�
�	�
�	�
�	�
�	�
�	�
�	�
�	�
�	�
�	�
�	�
�	�
�	�
�	�

在第二列中,我希望与输入文件中的可读值相同,而不是�

这里发生了什么?

我的方法值得推荐吗?

还存在哪些其他方法(没有 java ***: Encoding in Pig - Java solution)?

非常感谢您的任何建议。

【问题讨论】:

【参考方案1】:

我正在解决一个类似的问题。 是的,字符编码在 Java/Hadoop 世界中可能很棘手:)。

实际上,您已经非常接近了 - 解决方案是:

data = LOAD '$input' USING PigStorage() AS (col1:bytearray);

问题是您将 col1 指定为 chararray。 Chararray 是“Unicode UTF-8 格式的数组(字符串)”。但是,对于 iso-8859-1 中的输入数据,情况并非如此。 pig 脚本将您的数据解释为 UTF-8 而不是 iso-8859-1。您应该改为指定 bytearray。 Bytearray 不会以任何方式解释数据 - 你必须这样做(例如在你的 UDF 函数中)。

接下来,我们需要处理每一行:

parsed = foreach a generate flatten(my.testparser($0));

然后,在 UDF 函数 (my.testparser()) 中,我们将 iso-8859-1 编码更改为 utf-8

  ....
  val line:String = input.get(0).asInstanceOf[DataByteArray].get(), "windows-1250")
  ....

代码在 scala 中(我不是 python 人 - 抱歉),它需要输入 DataByteArray(PIG 中的 bytearray)并获取 的数组Scala.Bytes。然后这些字节被解释为 windows-1250。

也就是说,您的 UDF 应该保持不变,但输入需要更改为 Pig 中的 bytearray 和 UDF 中的等效数据类型

希望对你有帮助

【讨论】:

【参考方案2】:

以下是用 Python 定义的 UDF,它适用于那些不熟悉 Scala 的人:

#!/usr/bin/env python
# charsetConversion.py
import struct

@outputSchema("word:chararray")
def toUTF8(s):
        line = ‘.’join([struct.pack(‘B’, x).decode(‘iso-8859-1’) for x in s])
        return line

这里是用于注册 UDF、加载数据、将 UDF 应用于数据以及获取该数据的样本以检查解码是否按预期工作的 PIG 命令。

REGISTER 'charsetConversion.py' USING org.apache.pig.scripting.jython.JythonScriptEngine AS pyudf;
data = LOAD '$input' USING TextLoader AS (col1: bytearray);
final = FOREACH data GENERATE $0,pyudf.toUTF8(col1);
final_lim = LIMIT final 10;
DUMP final_lim;

正如xhudik 在他的回答中提到的,这里的重要部分是将您的字段定义为字节数组。

【讨论】:

以上是关于PIG UDF (Python) 字符集编码的主要内容,如果未能解决你的问题,请参考以下文章

用于 PIG 捐赠错误的 Python UDF

在 Talend 中实现 UDF 和 Pig 脚本逻辑

Pig ERROR 1075:从 UDF 接收到一个字节数组。无法确定如何将字节数组转换为字符串

使用元组进行 Pig 编程

Pig 中的 Python UDF

通过python UDF将文本文件导入pig