Redux: Как мне заставить Jython использовать модули Python, хранящиеся в Lib, в своем собственном файле jar при запуске в Hadoop?

Я пытаюсь использовать 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 сообщает, что я могу иметь только TWO​​strong > , потому что я здесь новый. Я надеюсь, что когда-нибудь хватит репутации, чтобы действительно поспособствовать этому фантастическому сайту!:)

В любом случае. LTWFTW - долгое время наблюдатель, писатель впервые - большое спасибо!

Ответы

Ответ 1

Интересно, будет ли упаковка вашего приложения OneJar улучшать ситуацию. Пожалуйста, попробуйте и отчитайтесь. Я просто стреляю в темноту.

Ответ 2

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.