基於 Jython (org.python.util.PythonInterpreter) 實現 Java 與 Python 互操作,適用於規則引擎、科學計算腳本化、動態配置等場景。本文總結三種主流調用模式並附完整代碼示例。
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
2.7.3
</dependency>
適用於極簡邏輯、動態表達式求值。
import org.python.util.PythonInterpreter;
public class InlineExecDemo {
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
// 定義元組
interpreter.exec("days=('Mon','Tue','Wed','Thu','Fri','Sat','Sun')");
// 讀取並打印
interpreter.exec("print(days[1])"); // 輸出: Tue
}
}
特點:無需外部文件,所有狀態保持在同一 Interpreter 實例中。
適用於業務邏輯封裝在 Python 模塊中,Java 僅作調用入口。
my_utils.py
def adder(a, b):
return a + b
Java 調用端
import org.python.core.PyFunction;
import org.python.core.PyInteger;
import org.python.core.PyObject;
import org.python.util.PythonInterpreter;
public class CallPyFunctionDemo {
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
// 1. 執行腳本文件,將函數定義載入命名空間
interpreter.execfile("C:/Python27/programs/my_utils.py");
// 2. 從命名空間獲取函數對象
PyFunction func = (PyFunction) interpreter.get("adder", PyFunction.class);
// 3. 構造參數並調用
PyObject result = func.__call__(new PyInteger(2010), new PyInteger(2));
// 4. 轉換返回值
System.out.println("answer = " + result.toString()); // answer = 2012
}
}
關鍵 API:execfile() 載入腳本 → get(name, Class) 取得可調用對象 → __call__(PyObject...) 執行調用。
適用於整個腳本即業務流程,無需 Java 參與交互。
input.py
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))
Java 啟動器
import org.python.util.PythonInterpreter;
public class ExecPyFileDemo {
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.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
}
}
PythonInterpreter 非線程安全,多線程環境下每線程創建實例或使用線程池隔離。ProcessBuilder 啟動 CPython 進程通過 STDIN/STDOUT/HTTP 交互。