Skriptsprachen für Java

JaclJythonJRuby

Jython

  1. Einführung
  2. Jython ist eine 100% pure Java Implementierung von Python. Jython wurde zuerst unter dem Namen JPython im Jahre 1997 veröffentlicht. Der Author der Sprache ist Jim Hugunin, der JPython bis 1999 weiterentwickelte. Barry Warsaw übernahm 1999 die Entwicklung. JPython wurde im Jahre 2000 in Jython umbenannt und wird seitdem als Source Forge Projekt entwickelt. Lange Zeit hatte hauptsächlich Samuele Pedroni an der Erhaltung und Weiterentwicklung der Sprache gearbeitet. Doch Pedroni trat zum Ende des Jahres 2004 zurück und widmete sich der Entwicklung von PyPy. Barry Warsaw machte Finn Bock zum Maintainer (Instandhalter). Die Entwicklung von Jython schreitet voran, jedoch wird der Prozess verlangsamt, da es einen Mangel an Entwicklern mit entsprechenden Kenntnissen und ausreichend Zeit gibt.

    Die aktuelle Version von Jython (2.2.1) kam am 14.10.2007 raus und beinhaltet alle Features von CPython 2.2. Diese Version ist die erste stabile Veröffentlichung seit 6 Jahren. Sie erweiterte Jython um einen Compiler (Jythonc), der Python Quelltext in eine Java Datei konvertiert.

    Zur offiziellen Homepage

  3. Anwendungsbeispiele
    1. Python Befehle in Java
    2. In unserem ersten Jython Beispiel benutzen wir die Python Klasse "math", um PI und E auszugeben. Außerdem ziehen wir noch die Wurzel mit Hilfe der Funktion sqrt von "math" um die Interaktion beider Programmierwelten zu zeigen. Wie man sieht, arbeitet der Python-Interpreter ähnlich wie der Tcl-Interpreter. Jedoch nutzen wir hier, statt der eval Methode, die exec Methode mit dem auszuführenden String. Ein PyObject könnte man auch in der exec Methode ausführen. Bei Fehlern würde man wieder eine Exception werfen, in diesem Fall eine PyException.

      //Einige Python Objekte importieren

      import
       org.python.core.PyInteger;
      import
       org.python.core.PyObject;
      import
       org.python.core.PyString;
      //PyException importieren

      import
       org.python.core.PyException;
      //Python Interpretierer importieren

      import
       org.python.util.PythonInterpreter;

      public class
       Math_As_Code {
      public static void
       main(String []args)
      try
       {
      //Python Interpretierer erzeugen

      PythonInterpreter python =
      new
       PythonInterpreter();
      //Interpretierer importiert math

      python.exec(
      "import math"
      );
      //Ein paar Ausgaben

      python.exec(
      "print 'Hello Jython World!'"
      );
      python.exec(
      "print math.pi"
      );
      python.exec(
      "print math.e"
      );
      //Variable setzen und verarbeiten

      python.set(
      "ourSetVariable"
      ,
      new
       PyInteger(25));
      python.exec(
      "ourSetVariable = math.sqrt(ourSetVariable)"
      );
      //Variable aus dem Interpretierer in Java Code holen...

      PyObject ourSetVariable = python.get(
      "ourSetVariable"
      );
      //...ausgeben...

      System.out.println(
      "Java-Ausgabe: "
       + ourSetVariable);
      python.exec (
      "print 'Python-Ausgabe: ' , "
       + ourSetVariable);
      //...und verändern

      python.set(
      "ourSetVariable"
      new
       PyString(
      "123 usw."
      ));
      python.exec(
      "print ourSetVariable"
      );
      catch
       (PyException e) {
      System.out.println(
      "PyException: "
       + e.getMessage());
      }
      }
      }

      Anmerkung: Dieses Beispiel soll die Interaktionsmöglichkeiten zeigen.

    3. Python Datei in Java
    4. Man kann, wie auch in Jacl, den Skript Code in einer Datei auslagern.

      Python Datei: math.py

      import
       math
      print
       
      "Hello Jython World"
       
      print
       math.pi
      print
       math.e
      print
       math.sqrt(25)

      Mit der Methode execfile führt man die Datei aus. Falls die Datei nicht existiert, wird eine PyException geworfen.

      Java Code:

      //PyException importieren

      import
       org.python.core.PyException;
      //Python Interpretierer importieren

      import
       org.python.util.PythonInterpreter;

      public class
       Math_As_File {
      public static void
       main(String []args)
      try
       {
      //Python Interpretierer erzeugen

      PythonInterpreter python =
      new
       PythonInterpreter();
      //execfile führt eine Datei aus

      python.execfile(
      "C:/Skripte/Jython/math.py"
      );
      catch
       (PyException e) {
      System.out.println(
      "PyException: "
       + e.getMessage());
      }
      }
      }

      Diese beiden Beispiele gehöhren zu den Grundlagen, um mit Jython zu arbeiten.
      Bis auf die Syntax und die Methodenbezeichnungen ist der Aufbau zu Jacl sehr ähnlich.

    5. Reguläre Ausdrücke
    6. Nun kommen wir zu einem sinnvolleren Beispiel. Hier arbeiten wir mit regulären Ausdrücken, um das erste Wort aus dem inputStr, dem man vorher einen Wert zuweisen sollte, zu filtern. Das Ergebnis wird im outputStr gespeichert.

      Python Datei: regexp.py

      import
       re
      getFirstWord = re.compile(
      "[A-za-z]+"
      )
      outputStr = getFirstWord.search(inputStr).group()

      Zuerst weisen wir der "Parameter-Variablen" inputStr einen Wert zu, welcher dann im Skript verarbeitet wird und anschließend geben wir das Ergebnis aus.

      Java Code:

      //Python Objekt PyString importieren

      import
       org.python.core.PyString;
      //PyException importieren

      import
       org.python.core.PyException;
      //Python Interpretierer importieren

      import
       org.python.util.PythonInterpreter;

      public class
       RegExp {
      public static void
       main(String []args)
      try
       {
      //Python Interpretierer erzeugen

      PythonInterpreter python =
      new
       PythonInterpreter();
      //Setzt inputString (dient als Parameter)

      jython.set(
      "inputStr"
      , new PyString(
      "***Erstes***Wort***"
      ));
      //inputStr verarbeiten

      python.execfile(
      "C:/Skripte/Jython/regexp.py"
      );
      //gibt "Erstes" aus

      System.out.println(jython.get(
      "outputStr"
      ));
      catch
       (PyException e) {
      System.out.println(
      "PyException: "
       + e.getMessage());
      }
      }
      }

    7. Der Compiler Jythonc
    8. Jetzt gehe ich auf Jythonc ein. Um erst einmal einen Einblick zu bekommen, was Jythonc erzeugt, habe ich eine leere Datei (empty.py) mit dem Befehl...

      jythonc empty.py
      ...in der Konsole in Java Code konvertiert. Als Ergebnis habe ich eine 52 Zeilen große Java Datei erhalten, die ein Grundgerürst darstellt. Das Einzige was sich ableiten lässt, ist der Pfad der Datei empty.py.



    9. Applet
    10. Bisher bin ich nur auf die einseitige Interaktion zwischen Python und Java eingegangen. Nun gehe ich auf Java Elemente im Python Code ein. In diesem Beispiel wollen wir mit folgendem Code ein einfaches Applet erzeugen:

      Python Datei: TestApplet.py

      #Zuerst importieren wir die Java Klasse Applet

      from
       
      java.applet
       
      import
       
      Applet

      #Hier erben wir von Applet

      class
       TestApplet ( 
      java.applet.Applet
       ):
      #Paint Methode

      def
       paint ( self, g ):
      g.drawString (
      "Ein Text"
      , 5, 5 )

      Bei der Eingabe in der Konsole von...

      python TestApplet.py
      ...merken wir das nichts passiert, weil der Quellcode erst einmal in Java Code konvertiert werden muss. Dieses Kunststück gelingt uns mit Jythonc, indem wir in der Konsole folgendes eingeben...
      pythonc TestApplet.py
      ...erhalten wir eine über 210 Zeilen (incl. Leerzeilen) schwere Java Datei aus einer ursprünglichen 7 Zeilen (incl. Kommentaren) großen Datei. Eine perfekte Implementierung ist dies nicht.



    11. Java Klasse in Python erweitern
    12. Man kann mit Python sowohl imperativ als auch - nicht wie in Tcl - objektorientiert programmieren. So bietet sich die Möglichkeit für Python von Java Klassen zu erben und zu erweitern. Zum Beispiel so:

      Python Datei: StringRandom.py:

      #Random Klasse importieren

      import
       java.util.Random
      #StringRandom erbt von der Klasse Random aus java.util

      class
       StringRandom (java.util.Random):
      #Hier wird die Methode "nextInt" überschrieben

      def
       
      nextInt
       ( self ):
      #Statt einem int gibt man hier einen String wieder

      return
       str ( java.util.Random.nextInt ( self ) )
      #StringRandom erzeugen

      x = StringRandom()
      #Überschriebende Methode aufrufen, um einen zufälligen Zahlen-String zu erhalten

      x.
      nextInt()

      #Methoden aus Random sind auch noch nutzbar

      x.
      nextLong()

      Anmerkung: Python arbeitet mit Zeilenvorschub um einen Block zu definieren, anstatt mit geschweiften Klammern, wie Java.
      Wie man im Beispiel sieht, ist man nicht gezwungen den Typ des Rückgabewertes einer Methode beim Vererben beizubehalten, da in Python kein Typ für den Rückgabewert angegeben wird. Damit können beliebige Objekte aus einer Methode zurückgegeben werden.

    13. Python Klasse in Java
    14. Für dieses Beispiel wird zunächst eine Python Klasse erstellt.

      Python Datei: HelloWorldClass.py

      class
       HelloWorldClass:
      #Der Konstruktor

      def
       
      __init__
       ( self ) :
      self.msg =
      "Hello World"
      #get Methode

      def
       
      getMsg
       ( self ) :
      return
       self.msg
      #set Methode

      def
       
      setMsg
       ( self , str ) :
      self.msg = str

      Um die Klasse benutzen zu können, läft die Klasse erstmal in Java durch den Interpretierer.

      Java Code: HelloWorld

      //PyException importieren

      import
       org.python.core.PyException;
      //Python Interpretierer importieren

      import
       org.python.util.PythonInterpreter;

      public class
       HelloWorld {
      public static void
       main(String []args)
      try
       {
      //Python Interpretierer erzeugen

      PythonInterpreter python =
      new
       PythonInterpreter();
      //Klasse erstellen

      python.execfile("C:/Skripte/Jython/HelloWorldClass.py");
      //Objekt erzeugen

      python.exec(
      "a = HelloWorldClass()"
      );
      //get Methdode aufrufen aus der Python Klasse

      python.exec(
      "print a.getMsg()"
      );
      //1.Möglichkeit

      //set und get Methdoden aufrufen

      python.exec(
      "a.setMsg('A Value')"
      );
      python.exec(
      "print a.getMsg()"
      );
      //2.Möglichkeit

      //a Objekt ändern

      python.set(
      "a"
      ,
      new
       String ( 
      "Text"
       ));
      python.exec(
      "print a"
      );
      catch
       (PyException e) {
      System.out.println(
      "PyException: "
       + e.getMessage());
      }
      }
      }

      Der Vorteil einer Skriptsprache ist Variablen nicht an einen Typ zu binden. In der 2. Möglichkeit kann Java nun davon Gebrauch machen.

    15. Java Interface in Python implementieren
    16. Das letzte Beispiel beschränkt sich auf die Implementierung eines Interfaces. In diesem Fall wird das Comparable Interface aus Java implementiert, welche die abstrakte Methode compareTo(Object) enthält. Dabei verzichten wird absichtlich auf die Implementierung der abstrakten Methode.

      Python Datei: Comp.py

      import
       
      java.lang.Comparable

      class
       Comp ( 
      java.lang.Comparable
       ) :
      #Der Konstruktor

      def
       
      __init__
       ( self ) :
      self.msg =
      "Default_Value"
      #Absichtlich kommentiert!

      #def compareTo ( obj ) :
      #...

      Da der Code nur interpretiert wird, wird nicht überprüft, ob man die compareTo(Object) Methode implementiert hat. Erst beim Aufruf der Methode erhält man folgende Fehlermeldung:
      AttributeError: abstract method "compareTo" not implemented

  4. Fazit
  5. Vorteile:

    Nachteile:

    Zwei Zitate von Sean McGrath (dem technischen Direktor von Propylon):

Autor: Michael Kaluza