2012-02-15 74 views
4

我真的想在我們的AWS Elastic MapReduce集羣中利用Pig中的Python UDF,但我無法完全正確地工作。不管我怎麼努力,我的豬的工作失敗,出現以下異常被記錄:如何在Elastic MapReduce中使用Python UDF和Pig?

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使用Python的UDF的豬?

回答

2

經過不少輪迴,我發現至少在彈性映射中減少了Hadoop的實現,Pig似乎忽略了CLASSPATH環境變量。我發現我可以使用HADOOP_CLASSPATH變量來控制類路徑。

當我意識到這一點,這是很容易得到的東西設置使用Python UDFS:

  • 安裝的Jython
    • sudo apt-get install jython -y -qq
  • 設置HADOOP_CLASSPATH環境變量。
    • export HADOOP_CLASSPATH=/usr/share/java/jython.jar:/usr/share/maven-repo/org/antlr/antlr-runtime/3.2/antlr-runtime-3.2.jar
      • jython.jar保證的Hadoop可以找到PyException類
      • ANTLR運行時,3.2.jar確保的Hadoop可以找到CharStream類
  • 創建緩存目錄爲Jython(這是documented in the Jython FAQ
    • sudo mkdir /usr/share/java/cachedir/
    • sudo chmod a+rw /usr/share/java/cachedir

我應該指出的是,這似乎直接反駁我發現同時尋找解決問題的對策等的建議是:

  • 設置CLASSPATH和PIG_CLASSPATH環境變量不似乎做任何事情。
  • 包含UDF的.py文件不需要包含在HADOOP_CLASSPATH環境變量中。
  • Pig register語句中使用的.py文件的路徑可能是相對的或絕對的,它似乎並不重要。
0

我最近面臨同樣的問題。你的答案可以簡化。您不需要安裝jython或創建緩存目錄。您確實需要將Jython jar包含在EMR引導腳本中(或者執行類似的操作)。我用以下幾行寫了一個EMR引導腳本。通過完全不使用s3cmd,通過使用作業流程(將文件放置在特定目錄中),可以進一步簡化這一點。通過s3cmd獲取UDF肯定不方便,但是,當使用豬的EMR版本時,我無法在s3上註冊udf文件。

如果您正在使用CharStream,則必須將該jar包括到piglib路徑中。根據您使用的框架,您可以將這些引導腳本作爲選項傳遞給您的工作,EMR通過其elastic-mapreduce ruby​​客戶端支持此腳本。一個簡單的選擇是將引導腳本放在s3上。

如果您在引導腳本中使用s3cmd,則需要另一個引導腳本來執行此類操作。這個腳本應該以bootstrap順序放在另一個之前。我正在擺脫使用s3cmd,但爲了我的成功嘗試,s3cmd取得了訣竅。此外,s3cmd可執行已安裝在豬圖像中亞馬遜(如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 
0

截至今天,電子病歷使用豬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; 
4

嗯......使用存儲在豬蟒蛇UDF EMR上運行,以澄清一些什麼,我只是在這裏讀書,在這一點上S3,這是因爲這條線在你的豬腳本簡單:

註冊「S3://path/to/bucket/udfs.py」使用Jython作爲了myNameSpace

也就是說,沒有類路徑修改必要的。我現在正在使用這個工具,儘管我沒有在udf中添加任何額外的Python模塊。我認爲這可能會影響你需要做的工作。