我真的想在我们的AWS Elastic MapReduce集群中利用Pig中的Python UDF,但我无法让事情正常运行。无论我尝试什么,我的猪作业都会失败,并记录以下异常:
ERROR 2998: Unhandled internal error. org/python/core/PyException
java.lang.NoClassDefFoundError: org/python/core/PyException
at org.apache.pig.scripting.jython.JythonScriptEngine.registerFunctions(JythonScriptEngine.java:127)
at org.apache.pig.PigServer.registerCode(PigServer.java:568)
at org.apache.pig.tools.grunt.GruntParser.processRegister(GruntParser.java:421)
at org.apache.pig.tools.pigscript.parser.PigScriptParser.parse(PigScriptParser.java:419)
at org.apache.pig.tools.grunt.GruntParser.parseStopOnError(GruntParser.java:188)
at org.apache.pig.tools.grunt.GruntParser.parseStopOnError(GruntParser.java:164)
at org.apache.pig.tools.grunt.Grunt.exec(Grunt.java:81)
at org.apache.pig.Main.run(Main.java:437)
at org.apache.pig.Main.main(Main.java:111)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.hadoop.util.RunJar.main(RunJar.java:156) Caused by: java.lang.ClassNotFoundException: org.python.core.PyException
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
... 14 more
在弹性MapReduce中为Pig使用Python UDF需要做什么?
答案 0 :(得分:4)
嗯......澄清一下我刚刚在这里阅读的内容,此时使用存储在s3上的EMR上运行的Pig中的python UDF,它就像你猪脚本中的这一行一样简单:
使用jython作为mynamespace注册's3://path/to/bucket/udfs.py'
也就是说,不需要修改类路径。我现在正在使用它,虽然有一点需要注意,我没有在我的udf中添加任何额外的python模块。我认为这可能会影响你需要做些什么来使其发挥作用。
答案 1 :(得分:2)
一旦我实现了这一点,就可以很容易地设置使用Python UDFS:
sudo apt-get install jython -y -qq
export HADOOP_CLASSPATH=/usr/share/java/jython.jar:/usr/share/maven-repo/org/antlr/antlr-runtime/3.2/antlr-runtime-3.2.jar
sudo mkdir /usr/share/java/cachedir/
sudo chmod a+rw /usr/share/java/cachedir
我应该指出,这似乎与我在寻找这个问题的解决方案时发现的其他建议直接相矛盾:
register
语句中使用的.py文件的路径可能是相对的或绝对的,似乎并不重要。答案 2 :(得分:0)
我最近遇到了同样的问题。你的答案可以简化。您根本不需要安装jython或创建缓存目录。您需要在EMR引导脚本中包含jython jar(或执行类似操作)。我用以下几行编写了一个EMR引导程序脚本。可以通过完全不使用s3cmd来进一步简化这一过程,而是使用您的作业流程(将文件放在某个目录中)。通过s3cmd获取UDF肯定不方便,但是,当使用EMR版本的猪时,我无法在s3上注册udf文件。
如果您正在使用CharStream,则必须将该jar包含在piglib路径中。根据您使用的框架,您可以将这些引导脚本作为选项传递给您的工作,EMR通过其elastic-mapreduce ruby客户端支持此功能。一个简单的选择是将引导脚本放在s3上。
如果您在引导脚本中使用s3cmd,则需要另一个执行此类操作的引导脚本。此脚本应以引导顺序放在另一个脚本之前。我正在远离使用s3cmd,但是对于我的成功尝试,s3cmd完成了这个伎俩。此外,s3cmd可执行文件已经安装在amazon的猪图像中(例如ami版本2.0和hadoop版本0.20.205。
脚本#1(播种s3cmd)
#!/bin/bash
cat <<-OUTPUT > /home/hadoop/.s3cfg
[default]
access_key = YOUR KEY
bucket_location = US
cloudfront_host = cloudfront.amazonaws.com
cloudfront_resource = /2010-07-15/distribution
default_mime_type = binary/octet-stream
delete_removed = False
dry_run = False
encoding = UTF-8
encrypt = False
follow_symlinks = False
force = False
get_continue = False
gpg_command = /usr/local/bin/gpg
gpg_decrypt = %(gpg_command)s -d --verbose --no-use-agent --batch --yes --passphrase-fd % (passphrase_fd)s -o %(output_file)s %(input_file)s
gpg_encrypt = %(gpg_command)s -c --verbose --no-use-agent --batch --yes --passphrase-fd %(passphrase_fd)s -o %(output_file)s %(input_file)s
gpg_passphrase = YOUR PASSPHRASE
guess_mime_type = True
host_base = s3.amazonaws.com
host_bucket = %(bucket)s.s3.amazonaws.com
human_readable_sizes = False
list_md5 = False
log_target_prefix =
preserve_attrs = True
progress_meter = True
proxy_host =
proxy_port = 0
recursive = False
recv_chunk = 4096
reduced_redundancy = False
secret_key = YOUR SECRET
send_chunk = 4096
simpledb_host = sdb.amazonaws.com
skip_existing = False
socket_timeout = 10
urlencoding_mode = normal
use_https = False
verbosity = WARNING
OUTPUT
脚本#2(播种jython罐子)
#!/bin/bash
set -e
s3cmd get <jython.jar>
# Very useful for extra libraries not available in the jython jar. I got these libraries from the
# jython site and created a jar archive.
s3cmd get <jython_extra_libs.jar>
s3cmd get <UDF>
PIG_LIB_PATH=/home/hadoop/piglibs
mkdir -p $PIG_LIB_PATH
mv <jython.jar> $PIG_LIB_PATH
mv <jython_extra_libs.jar> $PIG_LIB_PATH
mv <UDF> $PIG_LIB_PATH
# Change hadoop classpath as well.
echo "HADOOP_CLASSPATH=$PIG_LIB_PATH/<jython.jar>:$PIG_LIB_PATH/<jython_extra_libs.jar>" >> /home/hadoop/conf/hadoop-user-env.sh
答案 3 :(得分:0)
截至今天,在EMR上使用Pig 0.9.1,我发现以下内容已足够:
env HADOOP_CLASSPATH=$HADOOP_CLASSPATH:/path/to/jython.jar pig -f script.pig
其中script.pig
执行Python脚本的注册,但不是jython.jar
:
register Pig-UDFs/udfs.py using jython as mynamespace;