SpecialistOff.NET / Вопросы / Статьи / Фрагменты кода / Резюме / Метки / Помощь / Файлы
НазадМетки: python
It turns out to be remarkably simple to use Jython to create an interpreted language inside your application. Consider the greenhouse controller example from Thinking in Java. This is a situation where you want the end user – the person managing the greenhouse – to have configuration control over the system, and so a simple scripting language is an ideal solution. This is often called a domain-specific language (DSL) because it solves a particular domain problem.
To create the language, we’ll simply write a set of Python classes, and the constructor of each will add itself to a (static) master list. The common data and behavior will be factored into the base class Event. Each Event object will contain an action string (for simplicity – in reality, you’d have some sort of functionality) and a time when the event is supposed to run. The constructor initializes these fields, and then adds the new Event object to a static list called events (defining it in the class, but outside of any methods, is what makes it static):
# Jython/GreenHouseLanguage.py class Event: events = [] # static def __init__(self, action, time): self.action = action self.time = time Event.events.append(self) def __cmp__ (self, other): "So sort() will compare only on time." return cmp(self.time, other.time) def run(self): print("%.2f: %s" % (self.time, self.action)) @staticmethod def run_events(): Event.events.sort(); for e in Event.events: e.run() 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) if __name__ == "__main__": ThermostatNight(5.00) LightOff(2.00) WaterOn(3.30) WaterOff(4.45) LightOn(1.00) ThermostatDay(6.00) Bell(7.00) Event.run_events()
Note
To run this program say python GreenHouseLanguage.py or jython GreenHouseLanguage.py.
The constructor of each derived class calls the base-class constructor, which adds the new object to the list. The run() function sorts the list, which automatically uses the __cmp__() method defined in Event to base comparisons on time only. In this example, it only prints out the list, but in the real system it would wait for the time of each event to come up and then run the event.
The __main__ section performs a simple test on the classes.
The above file – which is an ordinary Python program – is now a module that can be included in another Python program. But instead of using it in an ordinary Python program, let’s use Jython, inside of Java. This turns out to be remarkably simple: you import some Jython classes, create a PythonInterpreter object, and cause the Python files to be loaded:
// Jython/GreenHouseController.java import org.python.core.*; import org.python.util.PythonInterpreter; public class GreenHouseController { public static void main(String[] args) throws PyException { PythonInterpreter interp = new PythonInterpreter(); 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()"); } }
The PythonInterpreter object is a complete Python interpreter that accepts commands from the Java program. One of these commands is execfile(), which tells it to execute all the statements it finds in a particular file. By executing GreenHouseLanguage.py, all the classes from that file are loaded into our PythonInterpreter object, and so it now “holds” the greenhouse controller language. The Schedule.ghs file is the one created by the end user to control the greenhouse. Here’s an example:
# Jython/Schedule.ghs Bell(7.00) ThermostatDay(6.00) WaterOn(3.30) LightOn(1.00) ThermostatNight(5.00) LightOff(2.00) WaterOff(4.45)
This is the goal of the interpreter design pattern: to make the configuration of your program as simple as possible for the end user. With Jython you can achieve this with almost no effort at all.
One of the other methods available to the PythonInterpreter is exec(), which allows you to send a command to the interpreter. In the above program, the run() function is called using exec().