Redux:在Hadoop中运行时,我如何让Jython使用存储在Lib中自己的jar文件中的Python模块?

2022-09-03 16:16:44

我试图在Hadoop 1.2.1中使用Jython来实现。除了陈旧的项目(如 code.google.com/p/happy)之外,我几乎没有看到Jython + Hadoop的惊人之处,并且其中的过时实现,所以也许我一开始就吠错了树......但这似乎是合理和可能的。我也非常了解Hadoop Streaming,通过它,我可以在Hadoop中使用Python而无需使用Jython,但这不是我在这里想要做的。$HADOOP_HOME/src/examples/python/WordCount.py

基本上,当我使用 调用嵌入式/独立的 Jython jar 文件时,它在我的 Python 中,但是当我使用 调用时,isn 不在我的路径中,并且脚本找不到我正在引用的 Python 模块。java -jar /full/path/to/myjythonjar.jar/full/path/to/myjythonjar.jar/Libsys.pathbin/hadoop jar /full/path/to/myjythonjar.jar input output...jar/Lib

这就是我正在做的事情...

我正在使用Jython jar的独立版本,并使用界面,大致如SO在这里和其他地方描述的那样;基本上如下:JarRunner

 cp jython-standalone-2.7-b1.jar jythonsalib_test.jar  
 jar ufe jythonsalib_test.jar org.python.util.JarRunner __run__.py  

也就是说,拿一个独立jar的副本,添加我的脚本名称,然后更改清单以执行 - 非常感谢@Frank Wierzbicki的这个宝石。__run__.pyJarRunner

当我直接运行时,这一切都工作正常,例如,

java -jar jythonsalib_test.jar

我的报告它包括,这正是我所期望的,它是我获取Python模块的路径(通过设置为空列表(失败)和只有该路径(有效)的经验测试)。sys.path'/full/path/to/jar/file/jythonsalib_test.jar/Lib'sys.path

当我在Hadoop中运行相同的jar时,例如,作为

bin/hadoop jar /full/path/to/jar/file/jythonsalib_test.jar input output

sys.path仅包括

['__classpath__', '__pyclasspath__']

我还使用了Jython独立jar版本2.5.4-rc1(具有上述相同的行为)和2.5.3(由于不相关的原因,这对我不起作用)。

正如在其他SO答案中指出的那样,我目前使用的解决方法基本上是直接添加我的jar的Lib目录,在Jython脚本中,如

import sys
sys.path.append('/full/path/to/jar/file/jythonsalib_test.jar/Lib')

这基本上是有效的 - 但这是一个分布式应用程序!我没有可以以这种方式引用的路径。其他SO文章提出了各种机制,但基本上都通过Python(Java,或Jython安装或Jython“注册表”(startup/rc)文件<10rep)添加到库路径(再次,没有链接)。当然,我可以使用HDFS或引导机制或其他机制将某些内容分发到计算节点,例如jar或Jython或其他任何东西,但是代码已经在jar中了!所以我不需要再次单独分发它...

所以,总而言之:看起来我需要在一个文件系统上,可以直接和单独地引用包含Python模块的jar文件。(类似于旧的)我如何说服一个嵌入式的、独立的 Jython jar 始终使用 Jar 文件的 Lib 子目录中的 Python 模块,而不单独指向(可能相同)jar 文件?java -jar jythonjar.jar -jar jythonjar.jar

或者:如何将相对路径链接添加到当前jar文件...?还是我错过了一些关于Hadoop,Jython或Java或......的更阴险和基本的东西?

我有一个船加载更多的链接,但SO告诉我,我只能有个链接,因为我是新来的。我希望有一天能获得足够的代表,以便能够真正为这个梦幻般的网站做出贡献!:)

无论如何。LTWFTW - 长期观察者,第一次作家 - 非常感谢!


答案 1

我想知道用OneJar打包你的应用程序是否会改善事情。请尝试并报告。我只是在黑暗中拍摄。


答案 2

Hadoop(运行 MR1 作业的 2.6.0-cdh5.4.2 版)+ Jython(2.7.0 版)仅在启动阶段出现此问题:即当 or 代码运行时,Jython 包含且不包含您需要的条目,从而导致错误消息。在远程映射器代码中,正确设置了 。mainToolsys.prefixnullsys.path/path/to/jarfile.jar/Libsys.path

一种选择是仅在远程映射器和化简器中使用 Jython。

如果需要在启动阶段运行 Jython,可以手动编辑 (在首次调用 之前)。sys.pathPythonInterpreter

String pathToJar = getClass().getProtectionDomain().getCodeSource().getLocation().getPath().toString();
PySystemState sys = Py.getSystemState;
sys.path.insert(0, new PyString(pathToJar));

请参阅此SO问题(或其他地方)以获取技巧。如果你首先看一下,你可能会认为它不会起作用,因为当你在Hadoop中运行它时,你实际上在临时目录中获得了分解的jar的路径,而不是原始的jar文件。没关系:这个分解的目录有一个目录,Jython会选择分解的目录,而不是不和谐的目录。pathToJarpathToJarLib

最后,我还假设你原来的工作罐是一个依赖于和排除的,就像Hadoop工作罐通常的情况一样。jar-with-dependenciesjython-standalonehadoop-core