跨語言調用常見於複用 Python 科學計算庫、NLP 模型、腳本邏輯。本文介紹 Jython 為基礎的三種調用方式(需引入 jython-standalone 依賴)。
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.3</version> <!-- 或最新版 -->
</dependency>
import org.python.util.PythonInterpreter;
public class DirectExec {
public static void main(String[] args) {
PythonInterpreter interp = new PythonInterpreter();
interp.exec("days = ('Mon','Tue','Wed','Thu','Fri','Sat','Sun')");
interp.exec("print(days[1])"); // 輸出:Tue
}
}
適用於簡單邏輯、動態腳本執行。
my_utils.py
def adder(a, b):
return a + b
Java 調用
import org.python.core.*;
import org.python.util.PythonInterpreter;
public class CallFunction {
public static void main(String[] args) {
PythonInterpreter interp = new PythonInterpreter();
interp.execfile("C:/Python27/programs/my_utils.py"); // 載入腳本
PyFunction func = (PyFunction) interp.get("adder", PyFunction.class);
PyObject result = func.__call__(new PyInteger(2010), new PyInteger(2));
System.out.println("answer = " + result); // 輸出:2012
}
}
關鍵:interp.get("函數名", PyFunction.class) 獲取函數物件,__call__ 傳遞 PyObject 參數。
input.py
print('hello')
numbers = [3,5,2,0,6]
print(numbers)
numbers.sort()
print(numbers)
numbers.append(0)
print(numbers)
print(numbers.count(0))
print(numbers.index(5))
Java 執行
public class ExecScript {
public static void main(String[] args) {
PythonInterpreter interp = new PythonInterpreter();
interp.execfile("C:/Python27/programs/input.py");
/* 控制台輸出:
hello
[3, 5, 2, 0, 6]
[0, 2, 3, 5, 6]
[0, 2, 3, 5, 6, 0]
2
3
*/
}
}
| 方案 | 優點 | 缺點 |
|---|---|---|
| Jython (本文) | 純 Java、無外部進程、共享記憶體 | 僅支援 Python 2.7 語法、效能較 CPython 低、無法用 C 擴展庫 |
| ProcessBuilder 執行 python3 | 支援完整 Python 3 生態、C 擴展 | 進程開銷大、序列化傳參複雜、延遲高 |
| gRPC / REST / ZeroMQ 微服務 | 語言無關、獨立部署、擴展性強 | 架構複雜、網路延遲、運維成本高 |
| GraalVM Polyglot API | 同一 JVM 運行多語言、高效能 | 技術較新、學習曲線陡峭 |