在進行開發的過程當中,偶爾會遇到須要使用Java調用Python腳本的時候,畢竟Python在諸如爬蟲,以及科學計算等方面具備自然的優點。最近在工做中遇到須要在Java程序中調用已經寫好的Python程序,故作一下記錄。html
1經常使用的Java調用Python腳本的兩種方式java
調用方式一般爲如下兩種:python
•經過Jython調用,即經過Jython.jar提供的類庫實現linux
•直接經過Java的Runtime實現,Runtime類的Runtime.getRuntime()開啓進程,執行python腳本文件shell
2經過Jython實現調用windows
Jython簡介函數
Jython主頁:http://www.jython.org/微服務
Jython是Python語言在Java平臺的實現,本質上,Jython是由Java編寫,其是在JVM上實現的Python語言。所以,能夠直接經過Jython在Java中調用Python。spa
Jython安裝.net
在安裝Jython以前,必須確保本地已經安裝了JDK。
1. 經過Jython的官網下載對應版本的安裝文件Installer和單獨的standalone jar兩個jar文件,放到特定的目錄下,如C:jython2.7.0;
2. 進入終端,切換到當前用於安裝Jython的jar文件所在的目錄下,執行java -jar jython_installer_2.7.0.jar,「固然也能夠直接進入目錄雙擊對應的jar文件進行安裝」;
3. 配置對應的環境變量,分別將對應的jar,lib目錄加到CLASSPATH和Path中:
–C:jython2.7.0jython.jar; 加入到CLASSPATH中
–C:jython2.7.0;C:jython2.7.0Lib;加入到Path中
此時在終端下執行jython命令,若是安裝成功,則會進入到Jython的交互環境,可與Python的交互環境同樣執行Python命令。同時也能夠經過jython xxx.py命令執行python腳本文件。
Jython執行Python腳本
在Java中直接嵌入Python語句的用法較少,且實際意義不大。
import org.python.util.PythonInterpreter;
public class Main {
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
//執行Python語句
interpreter.exec("import sys");
interpreter.exec("print 'hello'");
interpreter.exec("print 2**100");
}
}
直接經過Jython包調用寫好的Python腳本,根據程序執行時的要求,大致能夠分爲如下幾種狀況:
1.不須要經過Java程序向Python腳本中傳遞參數,也不須要獲取Python腳本之行後的返回值,則能夠經過文件流的方式直接打開腳本,並使用Jython的解釋器執行。
import org.python.util.PythonInterpreter;
import java.io.*;
public class Main {
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
//執行Python腳本文件
try {
InputStream filepy = new FileInputStream("C:xxx.py");
interpreter.execfile(filepy);
filepy.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.在Java中調用Python程序,同時須要傳遞參數和接收返回值。調用Python程序中的方法,可分爲兩種,一種是直接調用Python中寫好的方法函數,另外一種則是調用Python腳本的類中的函數。
–直接調用函數,經過PyFunction實現參數的傳遞和返回值的獲取
import org.python.core.*;
import org.python.util.PythonInterpreter;
public class Main{
public static void main(String[] args) {
PythonInterpreter inter = new PythonInterpreter();
//指定Python函數文件的路徑
String pythonFunc = "D:test.py";
inter.execfile(pythonFunc);
//獲取函數名test
PyFunction pyf = inter.get("test", PyFunction.class);
//向函數中傳遞參數並獲取返回結果
PyObject res = pyf.__call__(Py.newInteger(2), Py.newInteger(3));
System.out.print(res);
inter.cleanup();
inter.close();
}
}
– 在Java中調用Python對象實例方法,使用PyObject方法實例化Python對象,調用Python對象方法,傳遞參數並切接收返回值。
import org.python.core.*;
import org.python.util.PythonInterpreter;
public class Main{
public static void main(String[] args) {
PythonInterpreter inter = new PythonInterpreter();
//python類路徑
String pythonClass = "D:test_class.py";
//python 對象名
String pythonObjName = "cal";
// python類名
String pythonClazzName = "Calculator";
inter.execfile(pythonClass);
//實例化Python對象
inter.exec(PythonObjName + "=" + pythonClazzName + "()");
//獲取實例化的Python對象
PyObject pyObject = inter.get(pythonObjName);
//調用python對象方法,傳遞參數並接收返回值
PyObject res = pyObject.invoke("power", new PyObject[] {Py.newInteger(2), Py.newInteger(3)});
double power = Py.py2double(res);
System.out.print(power);
inter.cleanup();
inter.close();
}
}
其中,test_class.py文件的內容以下:
import math
class Calculator(object):
def power(x, y):
return math.pow(x, y)
Runtime類是Java中一個與JVM運行時環境有關的類,經過Runtime.getRuntime()能夠獲取到當前JVM運行時的環境。Runtime上的大部分方法都是實例方法,即每次在進行運行時調用時都要用到getRuntime()方法。使用Runtime類執行Python腳本的方法很是簡單粗暴,直接傳入當前平臺下的Python腳本執行命令便可。Java執行外部命令,主要方式仍是使用Runtime類的exec()方法調用平臺shell完成,如windows下的cmd,以及linux、unix、macOS下的的shell。
經過Runtime執行Python腳本,能夠直接經過命令向腳本中傳遞參數,並獲取Python腳本的輸出。
public class Main{
public static void main(String[] args) {
String cmd = "python xxx.py argv1 argv2 ...";
Process proc = Runtime.getRuntime().exec(cmd);
InputStream is = proc.getInputStream();
DataInputStream dis = new DataInputStream(is);
String str = dis.readLine();
proc.waitFor();
System.out.println(str);
}
}
3總結
以上兩種方法均可以實如今Java程序中調用Python腳本,但使用Jython進行調用時,效率較低,也會消耗較多資源,且調用的腳本須要Python的第三方依賴包時,須要在Jython中安裝第三方包。而使用Runtime調用腳本時,更多的依賴於運行的平臺,只要當前平臺安裝了對應的第三方依賴包,腳本就能夠順利執行,執行效率和直接執行Python腳本並無區別。
固然,在程序中不斷的進行嵌套調用,會下降程序的執行效率,增長程序的耦合複雜度,不方便未來的擴展,所以並不建議你們常用,而能夠考慮經過微服務的方法解決對應的問題。
文章還有不少不足之處,但願你們多多交流,多多指教。
參考連接
1.五大基於JVM的腳本語言https://coolshell.cn/articles/2631.html
2.Java調用Python http://tonl.iteye.com/blog/1918245
3.Java Runtime.exec()的使用https://blog.csdn.net/toneylyx/article/details/52623597
4.Why are there so many pythons https://www.oschina.net/translate/why-are-there-so-many-pythons
5.Jython www.jython.org