3

I am using below code to execute a python script from within a Java class:

import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.SimpleScriptContext;

StringWriter writer = new StringWriter();
ScriptEngineManager manager = new ScriptEngineManager();
ScriptContext context = new SimpleScriptContext();
context.setWriter(writer);
ScriptEngine engine = manager.getEngineByName("python");
engine.eval(new FileReader("test.py"), context);

I want to know how can I call a function inside test.py with above method and also pass some parameters to that function?

Note: I know a better way to execute the python script is through using Process but due to system requirements I do not want to use Process approach as it spawns a new process with each execution.

5
  • Use Jython instead of the primitive script engine. Commented Apr 9, 2015 at 16:23
  • @MalikBrahimi can you provide me an example of how can I use jython to execute a python script completely, execute a function inside python script while passing parameters to that function? Commented Apr 9, 2015 at 16:44
  • @MalikBrahimi also is the above requirement not possible to do with script engine? Commented Apr 9, 2015 at 16:46
  • @Perhaps, but it would be difficult and illogical even so. Commented Apr 9, 2015 at 16:47
  • @MalikBrahimi can you provide me an example of how can I use jython to execute a python script completely, execute a function inside python script while passing parameters to that function? Commented Apr 9, 2015 at 16:49

1 Answer 1

2

You need to change it a little to invoke a function.

ScriptContext context = new SimpleScriptContext();
context.setWriter(writer);
ScriptEngine engine = manager.getEngineByName("python");

// CHANGE: Set the context in the engine, so that invoking functions
// is done in the same scope as evaluating the script.
engine.setContext(context);

engine.eval(new FileReader("test.py"));

Invocable inv = (Invocable)engine;
inv.invokeFunction("func_name", param1, param2);

Basically, the Jython engine (which I assume you are using for scripting python) allows you to use its ScriptEngine as an Invocable. This means you can use it to call functions, provided that you are in the same "scope" as the script you have ran. This is achieved by setting the context in the engine instead of passing it as a parameter to eval.


Note: in your question, you say that you know that running the python in a separate process would probably be better. That's not necessarily true. For example, calling a function from it (and getting its returned value!) would be a lot harder if you ran it from a different process. The scripting extension allows you to do that.

Another option would be to use Jython directly, not through the standard Java scripting platform. But I don't have the knowledge to expand on that.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the answer! I have a doubt with what you meant by "which I assume you are using for scripting python"? I have jython_standalone 2.5.2 from maven. Is this what you meant? In my code I am importing import javax.script.ScriptContext;import javax.script.ScriptEngine;import javax.script.ScriptEngineManager;import javax.script.SimpleScriptContext;
It's not so much what you import. You just didn't mention what you were using as a Python engine, and I'm not sure if jython was the only one. So I said that I assume that you are using it. If it's on your classpath/build path than that's the one you are using.
what if I want to pass command line args to test.py? have a look to this question: stackoverflow.com/questions/31228021/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.