Оказывается, невероятно просто использовать Jython для создания интерпретируемого языка внутри вашего приложения. Рассмотрим пример диспетчера оранжереи, приведенный в Главе 8 книги Thinking in Java, 2nd edition. Это ситуация, в которой вы хотите, чтобы конечный пользователь - персона, управляющая оранжереей - имел возможность конфигурирования управления системой и простой скриптовый язык является идеальным решением.

Для создания языка мы просто напишем несколько Python'овских классов, а конструктор каждого из них добавит себя в (статический) список. Общие данные и поведение будут встроены в базовый класс Event. Каждый объект Event будет содержать строку action (для упрощения - в реальности, вы должны предоставить некоторую функциональность) и время, когда событие предназначается к запуску. Конструктор инициализирует эти поля, а замет добавляет новый объект Event в статический список, называемый events (определен в классе, но снаружи методов, что делает его статическим):

#:interpreter:GreenHouseLanguage.py

class Event:
  events =
[] # статический
  def __init__
(self, action, time):
    self.action = action
    self.time = time
    Event.events.append
(self)
 
# Используется функцией sort(). Это необходимо
  # сравнивать, основываясь только на времени:
  def __cmp__
(self, other):
   
if self.time < other.time: return -1
   
if self.time > other.time: return 1
   
return 0
 
def run(self):
    print
"%.2f: %s" % (self.time, self.action)

class LightOn(Event):
  def __init__
(self, time):
    Event.__init__
(self, "Light on", time)

class LightOff(Event):
  def __init__
(self, time):
    Event.__init__
(self, "Light off", time)

class WaterOn(Event):
  def __init__
(self, time):
    Event.__init__
(self, "Water on", time)

class WaterOff(Event):
  def __init__
(self, time):
    Event.__init__
(self, "Water off", time)

class ThermostatNight(Event):
  def __init__
(self, time):
    Event.__init__
(self,"Thermostat night", time)

class ThermostatDay(Event):
  def __init__
(self, time):
    Event.__init__
(self, "Thermostat day", time)

class Bell(Event):
  def __init__
(self, time):
    Event.__init__
(self, "Ring bell", time)

def run():
  Event.events.sort
();
 
for e in Event.events:
    e.run
()

# Для провреки это должно быть запущено командой:
# python GreenHouseLanguage.py
if __name__ == "__main__":
  ThermostatNight
(5.00)
 
LightOff(2.00)
 
WaterOn(3.30)
 
WaterOff(4.45)
 
LightOn(1.00)
 
ThermostatDay(6.00)
 
Bell(7.00)
 
run()
##~

Конструктор каждого наследуемого класса вызывает конструктор базового класса, который добавляет новый объект в список. Функция run( ) сортирует список, при этом автоматически используется метод __cmp__( ), который определен в базовом классе Event и сравнивает только по времени. В этом примере просто печатается список, но в реальной системе необходимо ждать наступления момента времени для каждого объекта, а затем запускать событие.

Секция __main__ выполняет простой тест классов.

Приведенный выше файл теперь является модулем, который может быть включен в другую Python программу для определения всех классов, которые он содержит. Но вместо обычной Python программы давайте будем использовать Jython внутри Java. Это можно сделать чрезвычайно просто: вы импортируете некоторые классы Jython, создаете объект PythonInterpreter, и это является причиной загрузки Python файлов:

//- interpreter:GreenHouseController.java

package interpreter;

import org.python.util.PythonInterpreter;

import org.python.core.*;

import junit.framework.*;



public class GreenHouseController extends TestCase  {
 
PythonInterpreter interp = new PythonInterpreter();

 
public void test() throws PyException  {
   
System.out.println("Loading GreenHouse Language");
    interp.execfile
("GreenHouseLanguage.py");
    System.out.println
("Loading GreenHouse Script");
    interp.execfile
("Schedule.ghs");
    System.out.println
("Executing GreenHouse Script");
    interp.exec
("run()");
 
}

 
public static void main(String[] args) throws PyException  {
   
junit.textui.TestRunner.run(GreenHouseController.class);
 
}

}
///:~

Объект PythonInterpreter является полным интерпретатором Python, который принимает команды из Java программы. Одной из этих команд является execfile( ), которая просит выполнить все выражения, которые можно найти в определенном файле. При выполнении GreenHouseLanguage.py все классы из этого файла загружаются в наш объект PythonInterpreter, и он теперь "хранит" язык управления оранжереей. Файл Schedule.ghs представляет собой файл, созданный конечным пользователем для управления оранжереей. Вот его пример:

//:! interpreter:Schedule.ghs
Bell(7.00)
ThermostatDay(6.00)
WaterOn(3.30)
LightOn(1.00)
ThermostatNight(5.00)
LightOff(2.00)
WaterOff(4.45)
///:~

Это цель шаблона проектирования итератора: сделать конфигурацию вашей программы настолько простой, насколько это возможно для конечного пользователя. С помощью Jython вы можете достигнуть этого практически без каких-либо усилий.

Один из методов, доступных у объекта PythonIterator, является метод exec( ), который позволяет вам посылать команды интерпретатору. Здесь функция run( ) вызывается с использованием exec( ).

Помните, что для запуска этой программы вы должны посетить http://jython.sourceforge.net, загрузить и установить Jython (фактически, вам необходим только jython.jar в вашем CLASSPATH). Как только он будет на месте, он может быть запущен как любая другая Java программа.