web-dev-qa-db-ja.com

JythonでJARファイルとしてPythonスクリプトを配布しますか?

私はほぼ2年間Python Pythonプログラマーでした。彼らはそれらのスクリプトも必要とします。

それらのいくつかはMac、いくつかのWindowsを持っています。これらをWindowsで作成しました。私はpy2exeまたはpy2appを使用してスクリプトのネイティブを作成する可能性を調査しましたが、彼らは私を決して満足させませんでした...

すべてのシステムにJVMが搭載されていることを知ったので、Jythonのようなものを使用して、スクリプトの1つの実行可能JARファイルを提供できますか?

これはどれほど実現可能か...つまり、Jythonのスクリプトの書き方がわからなかったのですが、書いたときに気にしませんでした...どのような問題が生じるのでしょうか?

55
Shrikant Sharat

Jar内のPythonファイルを配布するための現在の最良の手法は、Jythonのwikiのこの記事で詳しく説明されています。 http://wiki.python.org/jython/JythonFaq/DistributingJythonScripts

あなたの場合、JythonをインストールしてJython LibディレクトリをZipに圧縮したときに取得するjython.jarファイルを取得し、.pyファイルをZipで圧縮してから__run__.pyファイルを追加するとよいと思いますスタートアップロジック(このファイルはJythonによって特別に処理され、「Java -jar」でjarを呼び出すときに実行されるファイルです)。

このプロセスは本来あるべきものよりも明らかに複雑であるため、私たち(Jython開発者)はこれらのタスクを自動化するNiceツールを考案する必要がありますが、現時点ではこれらが最良の方法です。以下では、解決策の感覚をつかむために、上記の記事の下部にあるレシピ(問題の説明に合わせて若干変更されています)をコピーしています。

基本的なjarを作成します。

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

他のモジュールをjarに追加します。

$ 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 "__ == '__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

または、起動スクリプトをjarに追加した場合は、次のいずれかを使用します。

$ 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

Double -jarはいらいらするので、それを避けてもっと楽しくしたい場合:

$ Java -jar myapp.jar arg1

このようなことを将来のJythonに取り入れるまで、もう少し作業が必要です[更新: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);
    }
}

このコードをorg.python.utilパッケージに入れました。これは、将来のJythonに含めることを決定した場合に使用されるためです。コンパイルするには、次のようにjython.jar(またはmyapp.jar)をクラスパスに配置する必要があります。

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

次に、JarRunner.classをjarに追加する必要があります(クラスファイルはorg/python/util/JarRunner.classにある必要があります)。「org」ディレクトリでjarを呼び出すと、jarへのパス全体が取得されます。

$ jar uf org

これをマニフェストの更新に使用するファイルに追加します。適切な名前はmanifest.txtです。

Main-Class: org.python.util.JarRunner

次に、jarのマニフェストを更新します。

$ jar ufm myapp.jar manifest.txt

これで、次のようにアプリを実行できるようになります。

$ Java -jar myapp.jar
66

Jythonアプリの単純なコマンドライン呼び出しを作成でき、ユーザーがjythonインストールプロセスを実行する必要がなく、実行時にjythonスクリプトがライブラリの依存関係をsysに追加できるようにしたいという点で、同様の問題が発生しましたcore 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"))

Unixシステムでコマンドラインで「jython」ランチャーを明示的に実行すると、大きなシェルスクリプトが実行され、Javaコマンドラインコールが適切に形成されます。このjythonランチャーには依存関係があるようです。 jythonのコアインストールに戻ると、何らかの魔法によって、.pyスクリプト内から実行時にsys.pathに追加される.jarファイルを適切に処理できます。以下によって:

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ディストリビューションのlibディレクトリにあるスタンドアロンのjython.jarを呼び出すことで、ユーザーが.pyの使用を開始するために追加のインストール手順を実行する必要がないようにすることでした。スクリプトユーティリティ。

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.jarにすべての.classファイルをバンドルするという提案は、私にはまったく魅力的ではありませんでした。それは混乱であり、Java/Pythonハイブリッドアプリケーションをjythonディストリビューションに緊密にバインドします。だから、そのアイデアは飛ぶつもりはなかった。最後に、多くの検索を行った後、jython.orgでバグ#1776に遭遇しました。これは1年半にわたって重要であるとリストされていますが、jythonの最新の更新に修正が組み込まれているとは思いません。それでも、jythonに個別のjarファイルを含めることに問題がある場合は、これをお読みください。

http://bugs.jython.org/issue1776

そこには、これに対する一時的な回避策があります。私の場合、Apache POI jarファイルを独自のlibディレクトリに解凍し、sys.pathエントリを変更してjarではなくディレクトリを指すようにしました。

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

これで、ローカルのjython.jarを参照して、Java経由でjythonを実行すると、ユーティリティはただ実行されます。これで、単純なスクリプトまたはバッチファイルを作成して、.pyユーティリティのシームレスなコマンドラインエクスペリエンスを作成できます。ユーザーは、追加のインストール手順を実行せずに実行できます。

2
Robert Casey

「jythonc」コマンドは、.pyソースをJVMバイトコードにコンパイルできるはずです。これにより、任意のJavaインストールに移植可能になります。または、 http:/ /hell.org.ua/Docs/oreilly/other2/python/0596001886_pythonian-chp-25-sect-3.html

1
Yancy

ネイティブPythonインストールを必要としない方法でPythonスクリプトを配布するには、 Nuitka を試してみてください。基本的にPythonコードをC++コードに変換し、それを実際のネイティブバイナリにコンパイルします。

1
Tobias Kienzler