At present, the system has received a requirement that the platform can support running Python scripts, and our platform is written in Java. Therefore, we need to predict our final implementation plan.
After research, there are currently several ways for Java to call Python scripts.
1. Using jython
Jython is a JVM implementation of the Python programming language It is designed to run on the Java platform Jython programs can import and use any Java class Just like Java, Jython programs are compiled as bytecode One of the main advantages is that user interfaces designed in Python can use AWT, Swing, or SWT Package GUI elements The benefits of this approach are: . The disadvantages are also very obvious: . The Java. lang. runtime. exec (String command, String [] envp, File dir) method executes the specified string command in a separate process in the specified environment and working directory. This is a convenient method. The calling behavior of exec (command, envp, dir) is exactly the same as calling exec (cmdarray, envp, dir), where cmdarray is an array of all tags in the command The benefits of this approach are obvious: . But there are also many drawbacks: . The os. system () method executes a command (string) in a subshell. This method is implemented by calling the standard C function system () and has the same restrictions. If the command generates any output, it is sent to the interpreter's standard output stream. Whenever this method is used, the corresponding shell of the operating system is opened and the command is executed on it. Unfortunately, it does not return a value Jep uses JNI and CPython APIs to start the Python interpreter in the JVM. When you create an Interpreter instance in Java, a Python interpreter will be created for that Java Interpreter instance and kept in memory until the Interpreter instance is closed using Interpreter. close(). Due to the need to manage consistent Python thread state, the thread that creates the Interpreter instance must be reused in all method calls to that Interpreter instance Jep should work with any pure Python module. It can work with various CPython extensions. Developers have reported that Jep can work with NumPy, Scipy, Pandas, TensorFlow, Matplotlib, cvxpy, and more After the above configuration, we have set up the running environment for Jep and it is also very easy to use. According to our requirements, Jep can fully cover our usage scenarios. Below, we will discuss the advantages and disadvantages of Jep Disadvantages: . Summary: The current requirement is to support Python 3.0, and our platform's scripting function mainly changes input and output parameters or scene runtime parameters through scripts. Based on the above viewpoints, Jep is undoubtedly the best choice.<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.0</version>
</dependency>
Map<String, Object> binding = new HashMap<>();
binding.put("name", "zhangshan");
binding.put("age", "18");
try (PythonInterpreter interpreter = new PythonInterpreter(Py.java2py(binding))) {
interpreter.exec("varMap = globals()");
interpreter.exec("varMap.put('name', 'ls')");
interpreter.exec("varMap.put('sex', '1')");
PyObject vars = interpreter.get("varMap");
System.out.println(vars.toString());
}
2. Using command line mode
int a = 18;
int b = 23;
try {
String[] args1 = new String[] { "python", "/Users/rayduan/PycharmProjects/pythonProject/test.py", String.valueOf(a), String.valueOf(b) };
Process proc = Runtime.getRuntime().exec(args1);//implement py file
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
proc.waitFor();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
if __name__== '__main__':
print(sys.path)
3. Python calls Python scripts directly (by exposing interfaces)
#!/usr/local/bin/python3.7
import time
import os
count = 0
str = ('python b.py')
result1 = os.system(str)
print(result1)
while True:
count = count + 1
if count == 8:
print('this count is:',count)
break
else:
time.sleep(1)
print('this count is:',count)
print('Good Bye')
4. Use Jep
pip3 install jep
<dependency>
<groupId>black.ninia</groupId>
<artifactId>jep</artifactId>
<version>4.0.3</version>
</dependency
/**
*from python obtaining variable values from
* @param scriptContent
*/
public void runScriptWithReturn() {
try (SharedInterpreter interpreter = new SharedInterpreter()) {
interpreter.exec("import sys");
Object value = interpreter.getValue("sys.path");
System.out.println(value);
}
}
/**
*call python methods in the file
*/
public void runScriptWithFileMethod() {
JepConfig jepConfig = new JepConfig().addIncludePaths("/Users/rayduan/PycharmProjects/pythonProject");
SharedInterpreter.setConfig(jepConfig);
try (Interpreter interpreter = new SharedInterpreter()) {
interpreter.exec("from demo import *");
Object result = interpreter.invoke("func", 1, 2);
System.out.println(result);
}
}
/**
*by python script modification of values in variables
*/
public void runScriptWithChangeParam() {
try (Interpreter interpreter = new SharedInterpreter()) {
Map<String, Object> binding = new HashMap<>();
binding.put("name", "zhangshan");
binding.put("age", "18");
interpreter.set("vars", binding);
interpreter.exec("vars['name'] = 'ls'");
Map vars = interpreter.getValue("vars", Map.class);
System.out.println(vars);
}
}
Advantages: .