在Java項(xiàng)目中調(diào)用Python代碼有多種方法,包括使用Jython、ProcessBuilder、Java Scripting API和JNI。每種方法都有其適用場(chǎng)景和優(yōu)缺點(diǎn)。小編將詳細(xì)介紹這些方法,并提供示例代碼。
1. 使用Jython
Jython是一個(gè)由Java編寫(xiě)的Python解釋器,允許在Java環(huán)境中運(yùn)行Python代碼。Jython作為Python在Java中的完整實(shí)現(xiàn),提供了對(duì)Python庫(kù)和Java類(lèi)的訪問(wèn),具有豐富的資源庫(kù)。
步驟:
添加依賴(lài):在Maven項(xiàng)目中添加Jython依賴(lài)。
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.0</version>
</dependency>
執(zhí)行Python代碼:使用PythonInterpreter類(lèi)執(zhí)行Python代碼。
import org.python.util.PythonInterpreter;
import org.python.core.*;
public class InvokePython {
public static void main(String[] args) {
PythonInterpreter pythonInterpreter = new PythonInterpreter();
pythonInterpreter.exec("a='aaa'");
pythonInterpreter.exec("print(a)");
}
}
運(yùn)行
調(diào)用Python函數(shù):加載Python腳本文件并調(diào)用其中的函數(shù)。
import org.python.util.PythonInterpreter;
import org.python.core.*;
public class CallPythonFunction {
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.execfile("D:/Workspaces/J2EE/Test/config/my_utils.py");
PyFunction func = (PyFunction) interpreter.get("adder", PyFunction.class);
int a = 2010, b = 6;
PyObject pyobj = func._call_(new PyInteger(a), new PyInteger(b));
System.out.println("answer = " + pyobj.toString());
}
}
運(yùn)行
注意事項(xiàng):
Jython支持的Python版本為2.7,不支持Python 3.x。
Jython不再積極開(kāi)發(fā),可能不支持最新的Python庫(kù)。
2. 使用ProcessBuilder
ProcessBuilder用于啟動(dòng)和管理操作系統(tǒng)進(jìn)程,可以從Java中運(yùn)行外部Python腳本并捕獲輸出。
步驟:
編寫(xiě)Python腳本:創(chuàng)建一個(gè)Python腳本文件input.py 。
# open files
print('hello')
number = [3, 5, 2, 0, 6]
print(number)
number.sort()
print(number)
number.append(0)
print(number)
print(number.count(0))
print(number.index(5))
運(yùn)行
使用ProcessBuilder調(diào)用Python腳本:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class TestPython {
public static void main(String[] args) throws Exception {
ProcessBuilder pb = new ProcessBuilder("python", "D:/Workspaces/J2EE/Test/config/input.py");
Process process = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("Exited with error code : " + exitCode);
}
}
運(yùn)行
優(yōu)點(diǎn):
可以使用Python的所有庫(kù)和模塊。
支持最新版本的Python。
缺點(diǎn):
代碼相對(duì)復(fù)雜,可讀性較差。
需要處理進(jìn)程的輸入輸出流。
3. 使用Java Scripting API
Java Scripting API(JSR 223)允許Java通過(guò)統(tǒng)一接口調(diào)用各種腳本語(yǔ)言,包括Python。
步驟:
添加依賴(lài):確保項(xiàng)目中包含javax.script包。
使用ScriptEngineManager和ScriptEngine執(zhí)行Python代碼:import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class ScriptEngineExample {
public static void main(String[] args) {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("python");
try {
engine.eval("print('Hello from Python!')");
} catch (ScriptException e) {
e.printStackTrace();
}
}
}
運(yùn)行
優(yōu)點(diǎn):
提供統(tǒng)一接口調(diào)用多種腳本語(yǔ)言。
簡(jiǎn)化了腳本語(yǔ)言的集成。
缺點(diǎn):
需要額外的配置和依賴(lài)。
性能可能不如直接使用Jython或ProcessBuilder。
4. 使用JNI(Java Native Interface)
JNI使Java代碼能與C/C++編寫(xiě)的代碼交互,從而間接調(diào)用Python代碼。
步驟:
編寫(xiě)C/C++代碼:創(chuàng)建一個(gè)C/C++函數(shù)調(diào)用Python代碼。
使用JNI調(diào)用C/C++函數(shù):public class JNITest {
static {
System.loadLibrary("mylib");
}
private native void callPython();
public static void main(String[] args) {
new JNITest().callPython();
}
}
運(yùn)行
優(yōu)點(diǎn):
可以與C/C++代碼交互。
支持復(fù)雜的系統(tǒng)級(jí)操作。
缺點(diǎn):
需要編寫(xiě)和編譯C/C++代碼。
增加了項(xiàng)目的復(fù)雜性。
在選擇如何在Java中調(diào)用Python代碼時(shí),應(yīng)根據(jù)具體需求和項(xiàng)目特點(diǎn)進(jìn)行權(quán)衡。Jython適合頻繁調(diào)用Python代碼的場(chǎng)景,ProcessBuilder適用于簡(jiǎn)單腳本調(diào)用,Java Scripting API提供統(tǒng)一接口調(diào)用腳本語(yǔ)言,JNI適用于與C/C++代碼交互。根據(jù)實(shí)際需求選擇合適的方法,可以有效提升開(kāi)發(fā)效率和代碼的可維護(hù)性。