Оказывается, невероятно просто использовать 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 программа.
← | Обзор Python | Управление интерпретатором | → |