Vkladani JavaScriptu do Pythonu a Javy (pluginy)

Dlouho jsem hledal, jak uzivatelum snadno umoznit psat pluginy do me aplikace. Hodne se pouziva VBA (Visual Basic for Applications), Lisp a Lua. Me je nejblizsi JavaScript, navic v nem hodne lidi umi.

Moje potreba byla jednoducha: predat JavaScriptu promenne z Pythonu/Javy, pomoci JS s nima neco udelat a pote vratit vysledek.

Takze napriklad predam pole namerenych teplot za posledni hodinu. Uzivateluv algoritmus je vyhodnoti a vrati, jestli zapnout/vypnout kotel.

Java ma podporu vybornou, zvlaste od Javy 8. V Pythonu je to horsi, ale take funkcni.

Python

Zde je funkcni ukazka:

# https://blog.sqreen.io/embedding-javascript-into-python/
# http://stackoverflow.com/a/366763/1974494
# http://stackoverflow.com/a/601168/1974494

import signal
from contextlib import contextmanager
from py_mini_racer import py_mini_racer

ctx = py_mini_racer.MiniRacer()

# ---------------------

print( ctx.eval('1+1') )

# ---------------------

my_script_1 = """
function maxNumber(arr) {
    var largest = arr[0];
    for (var i = 0; i < arr.length; i++) {
        if (largest < arr[i] ) {
            largest = arr[i];
        }
    }
    return largest;
}
"""
ctx.eval(my_script_1)

arr = [3, 6, 2, 56, 32, 5, 89, 32]
max = ctx.call("maxNumber", arr)
print(max)

# ---------------------

my_script_2 = """
function sleep(delay) {
    var start = new Date().getTime();
    while (new Date().getTime() < start + (delay * 1000));
    return ":-)";
}
"""

ctx.eval(my_script_2)

class TimeoutException(Exception): pass

@contextmanager
def time_limit(seconds):
    def signal_handler(signum, frame):
        raise TimeoutException("Timed out!")
    signal.signal(signal.SIGALRM, signal_handler)
    signal.alarm(seconds)
    try:
        yield
    finally:
        signal.alarm(0)

try:
    with time_limit(5):
        result = ctx.call("sleep", 3)
        print(result)
except TimeoutException as msg:
    print("Timed out!")

try:
    with time_limit(5):
        result = ctx.call("sleep", 7)
        print(result)
except TimeoutException as msg:
    print("Timed out!")

# ---------------------

Prvni JavaScript najde v Python poli cisel nejvesti a vrati ho.
Druhy priklad je na pluginy vhodnejsi, nastavi timeout pro JavaScriptovy kod. Pokud uzivatel svuj algoritmus napr. zacykli, ukonci ho.

Zdrojak je na pochopeni dostatecny. A tady je jeho vystup:

/usr/bin/python3.5 /home/martin/PycharmProjects/JavaScript/miniracer_test1.py
2
89
:-)
Timed out!

Process finished with exit code 0

Java

package test.test;
 
public class User {
       
        private String name;
       
        public User() {
        }
       
        public String getName() {
                return name;
        }
       
        public void setName(String name) {
                this.name = name;
        }
}
package test.test;
 
import javax.script.Bindings;
import javax.script.Compilable; // Require Java 8 !!!
import javax.script.CompiledScript; // Require Java 8 !!!
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
 
public class JavaScriptInJava {
 
        public static void main(String[] args) throws ScriptException, NoSuchMethodException {
 
                ScriptEngineManager manager = new ScriptEngineManager();
                ScriptEngine engine = manager.getEngineByName("JavaScript");
 
                /* ----------------------------------------------------------------------- */
               
                // Put (string) param to JavaScript.
                engine.put("testString", "Hello, world!");
                engine.eval("print(testString)");
                // Put (string) param to JavaScript.
               
                /* ----------------------------------------------------------------------- */
 
                // Find max number in int array with JavaScript:
                int[] array = { 3, 6, 2, 56, 32, 5, 89, 32 };
                engine.put("arr", array);
 
                String script =
                                  "var largest = arr[0];                                "
                                + "function maxNumber(arr) {                            "
                                + "       for (var i = 0; i < arr.length; i++) {        "
                                + "               if (largest < arr[i] ) {              "
                                + "                       largest = arr[i];             "
                                + "               }                                     "
                                + "       }                                             "
                                + "       return largest;                               "
                                + "}                                                    "
                                + "maxNumber(arr);                                      ";
 
                Number result = (Number) engine.eval(script);
                System.out.println("Max=" + result.longValue());
                // Find max number in int array with JavaScript.
               
                /* ----------------------------------------------------------------------- */
 
                // Work with Java class from JavaScript:               
                String userScript =
                                  "user1.setName(\"Test User\");                "
                                + "print( user1.getName() );                    ";
               
                Bindings bindings = new SimpleBindings();
                User u = new User();
                bindings.put("user1", u);              
 
                engine.eval(userScript, bindings);
 
                        // Require Java 8 !!!
                // Compile JavaScript (faster):
                if (engine instanceof Compilable) {
                        System.out.println(" Compiling...");
                        Compilable compEngine = (Compilable) engine;
                        CompiledScript cs = compEngine.compile(userScript);
                        cs.eval(bindings);
                } else {
                        engine.eval(userScript, bindings);
                }
                // Compile JavaScript (faster).
                        // Require Java 8 !!!
               
                // Work with Java class from JavaScript.
               
                /* ----------------------------------------------------------------------- */
               
                // Use JavaScript function in Java code:
                String math =
                                  "function addition(a, b) {                    "
                                + "             return a+b;                     "
                                + "}                                            "
                                + "                                             "
                                + "function substraction(a, b) {                "
                                + "             return a-b;                     "
                                + "}                                            "
                                + "                                             ";
               
                engine.eval(math);
               
                Invocable inv = (Invocable) engine;
               
                int a = 10;
                int b = 5;
                System.out.println("A=" + a + " B=" + b);
               
                Object aPlusB = inv.invokeFunction("addition", a, b);
                System.out.println("A+B = " + aPlusB);
               
                Object[] inputParams = {
                                new Integer(10),
                                b
                                };
                Object aMinusB = inv.invokeFunction("substraction", inputParams);
                System.out.println("A-B = " + aMinusB);
               
                int x = (Integer) aPlusB + 1;
                System.out.println("aPlusB + 1 = " + x);
 
                // Use JavaScript function in Java code.
               
                /* ----------------------------------------------------------------------- */          
        }
}

Na ukazce je videt opet nalezeni nejvetsiho cisla. Mnohem zajimavejsi vsak je pristup k Java objektum z JavaScriptu – trida User.

Od Javy 8 je mozne JavaScript zkompilovat a tim ohromne urychlit jeho provadeni.

 

Jde pouze o ukazku, ze to jde 🙂

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *