Ответ 1
Интересно, будет ли упаковка вашего приложения OneJar улучшать ситуацию. Пожалуйста, попробуйте и отчитайтесь. Я просто стреляю в темноту.
Я пытаюсь использовать Jython для реализации в Hadoop 1.2.1. Я видел немного мало о Jython + Hadoop, кроме устаревших проектов (например, code.google.com/p/happy), и устаревшей реализации в $HADOOP_HOME/src/examples/python/WordCount.py
, поэтому, возможно, я начинаю с нуля неправильное дерево. но это кажется разумным и возможным. Я также очень хорошо знаю Hadoop Streaming, с помощью которого я могу использовать Python в Hadoop без использования Jython, но это не то, что я пытаюсь сделать здесь.
В основном, когда я вызываю встроенный/автономный jar файл Jython с помощью java -jar /full/path/to/myjythonjar.jar
, /full/path/to/myjythonjar.jar/Lib
находится в моем Python sys.path
, но когда я вызываю использование bin/hadoop jar /full/path/to/myjythonjar.jar input output
, ...jar/Lib
не находится на моем пути, и script не может найти модули Python, на которые я ссылаюсь.
Вот что я делаю...
Я использую автономную версию jython jar и используя интерфейс JarRunner
, примерно как описано здесь, здесь и других местах; в основном следующим образом:
cp jython-standalone-2.7-b1.jar jythonsalib_test.jar
jar ufe jythonsalib_test.jar org.python.util.JarRunner __run__.py
То есть, возьмите копию отдельного банку, добавьте мой script с именем __run__.py
и измените манифест для выполнения JarRunner
- многие благодаря @Frank Wierzbicki для этого драгоценного камня.
Все работает отлично, когда я запускаю непосредственно, например,
java -jar jythonsalib_test.jar
My sys.path
сообщает, что он включает в себя '/full/path/to/jar/file/jythonsalib_test.jar/Lib'
, что является именно тем, что я ожидаю, и это путь, из которого я получаю модули Python (эмпирически проверенный, установив sys.path
в null-list (не работает) ) и ТОЛЬКО этот путь (работает)).
Когда я запускаю эту же банку в Hadoop, например,
bin/hadoop jar /full/path/to/jar/file/jythonsalib_test.jar input output
sys.path
включает только
['__classpath__', '__pyclasspath__']
Я также использовал автономные jar-версии Jython версии 2.5.4-rc1 (который имеет такое же поведение, как описано выше) и 2.5.3 (это не работает для меня по несвязанным причинам).
Как указано в других ответах SO, обходной путь, который я использую в настоящее время, заключается в том, чтобы напрямую добавить мой каталог Lib моей jar, внутри Jython script, как
import sys
sys.path.append('/full/path/to/jar/file/jythonsalib_test.jar/Lib')
И это в основном работает - но это предназначено для распространения приложения! Нет пути, которым я могу ссылаться таким образом. Другие статьи SO предлагают различные механизмы, но все они в основном добавляют к путям библиотек (опять же, без ссылок, потому что у меня есть < 10rep) с помощью Python, как описано выше, Java или Jython или J реестра "registry" (startup/rc). Конечно, я мог бы использовать HDFS или механизмы начальной загрузки или другие механизмы для распространения чего-то на вычислительные узлы, такие как jar или Jython или что-то еще, но код уже находится в банке! Поэтому мне не нужно будет распространять его снова, отдельно...
Итак, в сумме: похоже, что мне нужно быть в файловой системе, которая может напрямую и отдельно ссылаться на файл jar, содержащий модули Python. (похоже на старый java -jar jythonjar.jar -jar jythonjar.jar
) Как убедить встроенный автономный Jython jar всегда использовать модули Python в подкаталоге Lib файла Jar без отдельного указания на (потенциально такой же) jar файл?
Или: как добавить ссылку относительного пути к текущему файлу jar...? Или мне не хватает чего-то более коварного и фундаментального в Hadoop или Jython или Java или...?
У меня было больше ссылок, но SO сообщает, что я могу иметь только TWOstrong > , потому что я здесь новый. Я надеюсь, что когда-нибудь хватит репутации, чтобы действительно поспособствовать этому фантастическому сайту!:)
В любом случае. LTWFTW - долгое время наблюдатель, писатель впервые - большое спасибо!
Интересно, будет ли упаковка вашего приложения OneJar улучшать ситуацию. Пожалуйста, попробуйте и отчитайтесь. Я просто стреляю в темноту.
Hadoop (версия 2.6.0-cdh5.4.2, выполняющая задания MR1) + Jython (версия 2.7.0) имеет только эту проблему на этапе запуска: то есть, когда выполняется код main
или Tool
Jython sys.prefix
- null
, а sys.path
не содержит записи /path/to/jarfile.jar/Lib
, которая вам нужна, в результате чего появляется сообщение об ошибке. В удаленном коде mapper, sys.path
установлен правильно.
Один из вариантов - использовать только Jython в удаленных картотеках и редукторах.
Если вам нужно запустить Jython на этапе запуска, вы можете отредактировать sys.path
вручную (до первого вызова PythonInterpreter
).
String pathToJar = getClass().getProtectionDomain().getCodeSource().getLocation().getPath().toString();
PySystemState sys = Py.getSystemState;
sys.path.insert(0, new PyString(pathToJar));
См. этот вопрос SO (или в другом месте) для трюка pathToJar
. Если вы сначала посмотрите на pathToJar
, вы можете подумать, что это не сработает, потому что когда вы запускаете его в Hadoop, вы фактически получаете путь к взорванному банку во временном каталоге, а не в исходном файле jar. Это нормально: этот взорванный каталог имеет каталог Lib
, а Jython собирает взорванный, а не jarred.
Наконец, я также предполагаю, что ваш исходный jar файл - это jar-with-dependencies
, который зависит от jython-standalone
и исключает hadoop-core
, как это обычно бывает для ящиков задания Hadoop.