Распространение моих скриптов Python в виде файлов JAR с помощью Jython?


Я был программистом Python в течение почти двух лет, и я привык писать небольшие скрипты для автоматизации некоторых повторяющихся задач, которые я должен был сделать в офисе. Теперь, видимо, мои коллеги заметили это, и они тоже хотят эти сценарии.

У некоторых из них есть Mac, некоторые окна; я сделал их на windows. Я исследовал возможность использования py2exe или даже py2app, чтобы сделать уроженцев моего скрипта, но они никогда не удовлетворяли меня...

Я узнал, что все они есть JVM на своих системах, так что я могу дать им один исполняемый файл JAR моего скрипта, используя что-то вроде Jython может быть?

насколько это возможно... Я имею в виду, я понятия не имел, как писать сценарии для Jython, и я не заботился об этом, когда писал их... какие проблемы это даст?

4 53

4 ответа:

лучшие современные методы распространения файлов Python в банке подробно описаны в этой статье на wiki Jython:http://wiki.python.org/jython/JythonFaq/DistributingJythonScripts

для вашего случая, я думаю, вы хотели бы взять jython.jar-файл, который вы получаете при установке Jython и zip каталог Jython Lib в него, а затем zip ваши. py файлы, а затем добавить __run__.py файл с логикой запуска (этот файл обрабатывается специально Jython и будет файл выполнен при вызове jar с "java-jar").

этот процесс, безусловно, сложнее, чем должно быть, и поэтому нам (разработчикам Jython) нужно придумать хороший инструмент, который автоматизирует эти задачи, но на данный момент это лучшие методы. Ниже я копирую рецепт в нижней части приведенной выше статьи (слегка измененный, чтобы соответствовать вашему описанию проблемы), чтобы дать вам представление о решении.

создать базовую фляги:

$ cd $JYTHON_HOME
$ cp jython.jar jythonlib.jar
$ zip -r jythonlib.jar Lib

добавить другие модули в банку:

$ cd $MY_APP_DIRECTORY
$ cp $JYTHON_HOME/jythonlib.jar myapp.jar
$ zip myapp.jar Lib/showobjs.py
# Add path to additional jar file.
$ jar ufm myapp.jar othermanifest.mf

добавить __run__.py модуль:

# Copy or rename your start-up script, removing the "__name__  == '__main__'" check.
$ cp mymainscript.py __run__.py
# Add your start-up script (__run__.py) to the jar.
$ zip myapp.jar __run__.py
# Add path to main jar to the CLASSPATH environment variable.
$ export CLASSPATH=/path/to/my/app/myapp.jar:$CLASSPATH

в MS Windows эта последняя строка, устанавливающая переменную среды CLASSPATH, будет выглядеть примерно так:

set CLASSPATH=C:\path\to\my\app\myapp.jar;%CLASSPATH%

или, опять же в MS Windows, используйте Панель управления и системные свойства для установки переменной среды CLASSPATH.

запустить приложение:

$ java -jar myapp.jar mymainscript.py arg1 arg2

или, если вы добавили свой запуск скрипта в банку, используйте один из следующих:

$ java org.python.util.jython -jar myapp.jar arg1 arg2
$ java -cp myapp.jar org.python.util.jython -jar myapp.jar arg1 arg2
$ java -jar myapp.jar -jar myapp.jar arg1 arg2

двойная банка немного раздражает, поэтому, если вы хотите избежать этого и получить более приятное:

$ java -jar myapp.jar arg1

вам придется сделать немного больше работы, пока мы не получим что-то вроде этого в будущем Jython [Update: JarRunner является частью Jython 2.5.1]. Вот некоторые Java-код, который ищет __run__.py автоматически, и запускает его. Обратите внимание, что это моя первая попытка в этом классе. Дайте мне знать, если это нужно улучшение!

package org.python.util;

import org.python.core.imp;
import org.python.core.PySystemState;

public class JarRunner {

    public static void run(String[] args) {
        final String runner = "__run__";
        String[] argv = new String[args.length + 1];
        argv[0] = runner;
        System.arraycopy(args, 0, argv, 1, args.length);
        PySystemState.initialize(PySystemState.getBaseProperties(), null, argv);
        imp.load(runner);
    }

    public static void main(String[] args) {
        run(args);
    }
}

я положил этот код в организацию.питон.пакет util, так как именно туда он пойдет, если мы решим включить его в будущий Jython. Чтобы скомпилировать его, вам нужно будет поставить jython.jar (или ваш myapp.jar) в путь к классам, например:

$ javac -classpath myapp.jar org/python/util/JarRunner.java

тогда вам нужно будет добавить JarRunner.класс для вашего jar (файл класса должен быть в org/python/util / JarRunner.класс) вызов jar в каталоге "org" позволит получить весь путь в ваш сосуд.

$ jar uf org

добавьте это в файл, который вы будете использовать для обновления манифеста, хорошее имя манифеста.txt:

Main-Class: org.python.util.JarRunner

затем обновите манифест jar:

$ jar ufm myapp.jar manifest.txt

теперь вы должны быть в состоянии запустить свое приложение следующим образом:

$ java -jar myapp.jar

я испытал аналогичную проблему в том, что я хочу иметь возможность создавать простые вызовы командной строки для моих приложений jython, не требуя, чтобы пользователь проходил процесс установки jython и мог иметь сценарии Jython, добавляющие зависимости библиотеки во время выполнения в sys.путь, чтобы включить основной код java.

# append Java library elements to path
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "lib", "poi-3.8-20120326.jar"))

при запуске 'Jython' launcher явно в командной строке, в системах Unix, он просто запускает большой сценарий оболочки, чтобы правильно сформировать командную строку java вызов. Эта пусковая установка jython, похоже, зависит от того, чтобы вернуться к основной установке jython, и каким-то образом магия позволяет правильно обрабатывать .файлы jar добавляются в систему.путь во время выполнения из моих скриптов. py. Вы можете увидеть, что такое вызов и заблокировать выполнение следующим образом:

jython --print run_form.py
java -Xmx512m -Xss1024k -Dfile.encoding=UTF-8 -classpath /Applications/jython2.5.2/jython.jar: -Dpython.home=/Applications/jython2.5.2 -Dpython.executable=/Applications/jython2.5.2/bin/jython org.python.util.jython run_form.py

но он все еще просто запускает JVM и запускает файл класса. Поэтому моя цель была, чтобы быть в состоянии сделать это в Java вызов отдельного языка Jython.jar присутствует в моем дистрибутиве каталог lib, поэтому пользователям не нужно будет делать никаких дополнительных шагов установки, чтобы начать использовать my .py scripted utilities.

java -Xmx512m -Xss1024k -classpath ../../lib/jython.jar org.python.util.jython run_form.py

проблема в том, что поведение достаточно отличается, что я бы получить ответы, как это:

  File "run_form.py", line 14, in <module>
    import xls_mgr
  File "/Users/test/Eclipse/workspace/test_code/py/test/xls_mgr.py", line 17, in <module>
    import org.apache.poi.hssf.extractor as xls_extractor
ImportError: No module named apache

теперь вы можете сказать, что я должен просто добавить файлы jar в путь-classpath, который на самом деле я пытался, но я бы получил тот же результат.

предложение связывать все из вашего .файлы классов в jython.баночка не звучала взывая ко мне вообще. Это было бы беспорядком и слишком сильно привязало бы гибридное приложение Java/Python к дистрибутиву jython. Так что эта идея не собиралась летать. Наконец, после долгих поисков, я наткнулся на ошибку #1776 в jython.org, который был указан как критический в течение полутора лет, но я не вижу, чтобы последние обновления jython включали исправление. Тем не менее, если у вас возникли проблемы с включением Jython в ваши отдельные файлы jar, вы должны прочитать этот.

http://bugs.jython.org/issue1776

там вы найдете временное решение для этого. В моем случае я взял файл Apache POI jar и unjar'Ed его в свой собственный отдельный каталог lib, а затем изменил sys.запись пути, чтобы указать на каталог вместо jar:

sys.path.append('/Users/test/Eclipse/workspace/test_code/lib/poi_lib')

теперь, когда я запускаю jython через java, ссылаясь на мой локальный jython.банку, утилита работает просто превосходно. Теперь я могу создавать простые скрипты или пакетные файлы для создания бесшовной командной строки для утилит my .py, которые пользователь может запускать без каких-либо дополнительных шагов установки.

команда 'jythonc' должна быть способна скомпилировать ваш источник .py в байт-код JVM, что должно сделать его переносимым для любой установки Java. Или так я читал на: http://hell.org.ua/Docs/oreilly/other2/python/0596001886_pythonian-chp-25-sect-3.html

для распространения ваших скриптов Python таким образом, чтобы не требовалась собственная установка Python, вы также можете попробовать Nuitka, который в основном переводит ваш код Python в код C++, который затем компилируется в истинный собственный двоичный файл.