2009-08-10 10 views
53

Jestem programistą Pythona od prawie dwóch lat i jestem przyzwyczajony do pisania małych skryptów w celu zautomatyzowania niektórych powtarzających się zadań, które musiałem wykonywać w biurze. Teraz najwyraźniej moi koledzy to zauważyli i oni też chcą tych skryptów.Dystrybucja moich skryptów w języku Python jako plików JAR za pomocą Jython?

Niektóre z nich mają Mac, niektóre Windows; Zrobiłem je w oknach. Zbadałem możliwość użycia py2exe, a nawet py2app, aby stworzyć tubylców z mojego skryptu, ale nigdy mnie nie satysfakcjonowało ...

Dowiedziałem się, że wszystkie mają JVM na swoich systemach, więc mogę dać im jeden plik wykonywalny pliku JAR mojego skryptu przy użyciu czegoś takiego jak Jython może być?

Jak to możliwe ... To znaczy, nie miałem pojęcia, jak napisać skrypty do Jythona, nie obchodziło mnie to, gdy je pisałem ... jakie problemy to przyniesie?

Odpowiedz

65

Najlepsze aktualnych technik dystrybucji plików Pythona w słoiku są szczegółowo opisane w tym artykule na jython za wiki: http://wiki.python.org/jython/JythonFaq/DistributingJythonScripts

Twoim przypadku, myślę, że chcesz wziąć Jython plik .jar, który otrzymasz po zainstalowaniu Jythona i skompresowaniu do niego katalogu Jython Lib, a następnie zapakowaniu plików .py w, a następnie dodaniu pliku __run__.py z logiką uruchamiania (ten plik jest traktowany specjalnie przez Jython i będzie plikiem wykonywane, gdy wywołasz słoik za pomocą "java -jar").

Proces ten jest zdecydowanie bardziej skomplikowany niż powinien, więc my (programiści Jython) musimy wymyślić ładne narzędzie, które zautomatyzuje te zadania, ale na razie są to najlepsze metody. Poniżej przepisuję przepis na dole powyższego artykułu (nieco zmodyfikowany, aby pasował do twojego opisu problemu), aby dać ci sens rozwiązania.

Tworzenie podstawowego słoika:

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

dodać inne moduły do ​​słoika:

$ 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 

dodać moduł __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 

na MS Windows, tej ostatniej linii, ustawienie zmiennej środowiskowej CLASSPATH wyglądałoby mniej więcej tak:

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

Lub ponownie w systemie MS Windows, użyj panelu sterowania i właściwości systemu, aby ustawić zmienną środowiskową CLASSPATH.

Uruchom aplikację:

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

Lub, jeśli dodano skrypt startowy do słoika, należy zastosować jedną z następujących czynności:

$ 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 

Podwójna -jar jest rodzajem denerwujące, więc jeśli chcesz tego uniknąć i uzyskać bardziej przyjemne:

$ java -jar myapp.jar arg1 

Będziesz musiał zrobić trochę więcej pracy il dostajemy coś takiego do przyszłego Jython [Update: JarRunner jest częścią Jython 2.5.1]. Oto kod Java, który automatycznie wyszukuje numer __run__.py i uruchamia go. Zauważ, że to moja pierwsza próba na tej klasie. Daj mi znać, czy to wymaga poprawy!

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); 
    } 
} 

umieścić ten kod na opakowaniu org.python.util, ponieważ to gdzie to udać, jeśli zdecydujemy się umieścić go w przyszłej Jython. Aby go skompilować, musisz umieścić jython.jar (lub myapp.jar) na ścieżce klasy jak:

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

Następnie trzeba dodać JarRunner.class do słoika (plik klasa musisz być w org/python/util/JarRunner.class) wywołując jar w katalogu "org" dostaniesz całą ścieżkę do twojego słoika.

$ jar uf org 

Dodaj to do pliku, który można wykorzystać do aktualizacji manifestu, dobre imię manifest.txt:

Main-Class: org.python.util.JarRunner 

następnie zaktualizować Jar w manifeście:

$ jar ufm myapp.jar manifest.txt 

teraz powinieneś być w stanie uruchomić swoją aplikację w następujący sposób:

$ java -jar myapp.jar 
+0

hej Frank, dzięki za wgląd, naprawdę .. jedna rzecz, otrzymuję błąd na polecenie "zip myapp .jar Lib/showobjs.py "... co to ma zrobić? –

+0

Najprawdopodobniej interpreter jython musi zostać wywołany zanim mój skrypt będzie mógł coś zrobić ... co mówi mi, że "java -jar MyScript.jar" do uruchomienia mojego skryptu Pythona nie jest możliwy. Dziękuję bardzo, Frank! –

+0

Powinieneś być w stanie skonfigurować rzeczy, aby działał "java -jar MyScript.jar". Później dzisiaj będę edytować moje kroki, aby zrobić bardziej konkretny przykład. –

1

Komenda 'jythonc' powinna być w stanie skompilować swoje źródło .py do kodu bajtowego JVM, co powinno umożliwić jego przenoszenie do dowolnej instalacji w języku Java. Albo więc czytam w: http://hell.org.ua/Docs/oreilly/other2/python/0596001886_pythonian-chp-25-sect-3.html

+3

Dzięki za link .. Nie wiedziałem o jythonc, ale zdałem sobie sprawę, że jythonc nie jest już dłużej utrzymywany ... http://www.jython.org/archive/22/jythonc.html I nie mogłem znaleźć żadnej pomocy, jak użyć polecenia jython do tworzenia słoików ... jakiejkolwiek pomocy w tym cenionym –

2

Doświadczyłem podobnego problemu, ponieważ chcę móc tworzyć proste wywołania z linii poleceń dla moich aplikacji jython, nie wymagać od użytkownika przechodzenia przez proces instalacyjny jython i mieć możliwość dołączania skryptów jython do zależności bibliotek w środowisku wykonawczym do sys.path, aby uwzględnić podstawowy kod 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")) 

Po uruchomieniu „jython” wyrzutnię wyraźnie w wierszu polecenia na systemach Unix, to po prostu działa wielki skrypt właściwie tworzą linię wywołania polecenia Java. Wydaje się, że ten program uruchamiający jython jest zależny od powrotu do podstawowej wersji jython, a dzięki magii pozwala na prawidłowe dodawanie plików .jar do sys.path w czasie wykonywania z moich skryptów .py. Można zobaczyć, co jest wywołanie i wykonanie bloku brzmienie:

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 

ale to wciąż tylko rozpalania JVM i uruchomienie pliku klasy. Moim celem było umożliwienie wywołania tego java do samodzielnego pliku jython.jar znajdującego się w katalogu lib mojej dystrybucji, aby użytkownicy nie musieli wykonywać żadnych dodatkowych kroków instalacyjnych, aby rozpocząć korzystanie z moich narzędzi skryptowych .py.

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

Problem jest taki, że zachowanie jest na tyle różne, że chciałbym uzyskać odpowiedzi jak to:

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 

Teraz można powiedzieć, że należy po prostu dodać pliki jar do -classpath, który w rzeczywistości Próbowałem, ale uzyskałbym ten sam rezultat.

Zasugerowanie powiązania wszystkich plików .class w pliku jython.jar nie brzmiało dla mnie wcale zachęcająco. Byłby to bałagan i zbyt mocno związałby aplikację hybrydową Java/Python z dystrybucją Jython. Więc ten pomysł nie będzie latać. W końcu, po wielu poszukiwaniach, natknąłem się na bug # 1776 na jython.org, który został wymieniony jako krytyczny przez półtora roku, ale nie widzę, aby najnowsze aktualizacje jython zawierały poprawkę. Jeśli jednak masz problemy z posiadaniem jython, to oddzielne pliki jar, powinieneś to przeczytać.

http://bugs.jython.org/issue1776

Tam znajdziesz tymczasowe obejście tego. W moim przypadku, wziąłem plik jar Apache POI i unjar'ed go w osobnym katalogu lib, a następnie zmodyfikowany wpis sys.path pkt do katalogu zamiast słoika:

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

Teraz, kiedy Uruchomiłem jython za pomocą java, odwołując się do mojego lokalnego jython.jar, narzędzie działa po prostu brzoskwiniowo. Teraz mogę tworzyć proste skrypty lub pliki wsadowe, aby zapewnić bezproblemową obsługę wiersza poleceń dla moich narzędzi .py, które użytkownik może uruchomić bez dodatkowych czynności instalacyjnych.

+0

To jest dobry post, dziękuję za podzielenie się swoim doświadczeniem i wiedzą. Pracuję też z jythonem i doświadczam takich samych problemów jak ty. (+1) – Eder

0

Aby dystrybuować skrypty w języku Python w sposób niewymagający natywnej instalacji w języku Python, można także wypróbować Nuitka, który zasadniczo tłumaczy kod Pythona na kod C++, który jest następnie kompilowany do prawdziwego natywnego pliku binarnego.

Powiązane problemy