java 调用python脚本过程_通过Java调用Python脚本
在進(jìn)行開發(fā)的過程中,偶爾會遇到需要使用Java調(diào)用Python腳本的時候,畢竟Python在諸如爬蟲,以及科學(xué)計算等方面具有天然的優(yōu)勢。最近在工作中遇到需要在Java程序中調(diào)用已經(jīng)寫好的Python程序,故做一下記錄。
1常用的Java調(diào)用Python腳本的兩種方式
調(diào)用方式通常為以下兩種:
?通過Jython調(diào)用,即通過Jython.jar提供的類庫實現(xiàn)
?直接通過Java的Runtime實現(xiàn),Runtime類的Runtime.getRuntime()開啟進(jìn)程,執(zhí)行python腳本文件
2通過Jython實現(xiàn)調(diào)用
Jython簡介
Jython主頁:http://www.jython.org/
Jython是Python語言在Java平臺的實現(xiàn),本質(zhì)上,Jython是由Java編寫,其是在JVM上實現(xiàn)的Python語言。因此,可以直接通過Jython在Java中調(diào)用Python。
Jython安裝
在安裝Jython之前,必須確保本地已經(jīng)安裝了JDK。
1. 通過Jython的官網(wǎng)下載對應(yīng)版本的安裝文件Installer和單獨的standalone jar兩個jar文件,放到特定的目錄下,如C:jython2.7.0;
2. 進(jìn)入終端,切換到當(dāng)前用于安裝Jython的jar文件所在的目錄下,執(zhí)行java -jar jython_installer_2.7.0.jar,「當(dāng)然也可以直接進(jìn)入目錄雙擊對應(yīng)的jar文件進(jìn)行安裝」;
3. 配置對應(yīng)的環(huán)境變量,分別將對應(yīng)的jar,lib目錄加到CLASSPATH和Path中:
–C:jython2.7.0jython.jar; 加入到CLASSPATH中
–C:jython2.7.0;C:jython2.7.0Lib;加入到Path中
此時在終端下執(zhí)行jython命令,如果安裝成功,則會進(jìn)入到Jython的交互環(huán)境,可與Python的交互環(huán)境一樣執(zhí)行Python命令。同時也可以通過jython xxx.py命令執(zhí)行python腳本文件。
Jython執(zhí)行Python腳本
直接在Java中嵌入Python語句
在Java中直接嵌入Python語句的用法較少,且實際意義不大。
import org.python.util.PythonInterpreter;
public class Main {
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
//執(zhí)行Python語句
interpreter.exec("import sys");
interpreter.exec("print 'hello'");
interpreter.exec("print 2**100");
}
}
在Java中執(zhí)行已經(jīng)編寫好的名為xxx.py的 Python腳本
直接通過Jython包調(diào)用寫好的Python腳本,根據(jù)程序執(zhí)行時的要求,大體可以分為以下幾種情況:
1.不需要通過Java程序向Python腳本中傳遞參數(shù),也不需要獲取Python腳本之行后的返回值,則可以通過文件流的方式直接打開腳本,并使用Jython的解釋器執(zhí)行。
import org.python.util.PythonInterpreter;
import java.io.*;
public class Main {
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
//執(zhí)行Python腳本文件
try {
InputStream filepy = new FileInputStream("C:xxx.py");
interpreter.execfile(filepy);
filepy.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.在Java中調(diào)用Python程序,同時需要傳遞參數(shù)和接收返回值。調(diào)用Python程序中的方法,可分為兩種,一種是直接調(diào)用Python中寫好的方法函數(shù),另一種則是調(diào)用Python腳本的類中的函數(shù)。
–直接調(diào)用函數(shù),通過PyFunction實現(xiàn)參數(shù)的傳遞和返回值的獲取
import org.python.core.*;
import org.python.util.PythonInterpreter;
public class Main{
public static void main(String[] args) {
PythonInterpreter inter = new PythonInterpreter();
//指定Python函數(shù)文件的路徑
String pythonFunc = "D:test.py";
inter.execfile(pythonFunc);
//獲取函數(shù)名test
PyFunction pyf = inter.get("test", PyFunction.class);
//向函數(shù)中傳遞參數(shù)并獲取返回結(jié)果
PyObject res = pyf.__call__(Py.newInteger(2), Py.newInteger(3));
System.out.print(res);
inter.cleanup();
inter.close();
}
}
– 在Java中調(diào)用Python對象實例方法,使用PyObject方法實例化Python對象,調(diào)用Python對象方法,傳遞參數(shù)并切接收返回值。
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);
//調(diào)用python對象方法,傳遞參數(shù)并接收返回值
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文件的內(nèi)容如下:
import math
class Calculator(object):
def power(x, y):
return math.pow(x, y)
通過Runtime.getRuntime().exec()實現(xiàn)調(diào)用
Runtime類是Java中一個與JVM運行時環(huán)境有關(guān)的類,通過Runtime.getRuntime()可以獲取到當(dāng)前JVM運行時的環(huán)境。Runtime上的大部分方法都是實例方法,即每次在進(jìn)行運行時調(diào)用時都要用到getRuntime()方法。使用Runtime類執(zhí)行Python腳本的方法非常簡單粗暴,直接傳入當(dāng)前平臺下的Python腳本執(zhí)行命令即可。Java執(zhí)行外部命令,主要方式還是使用Runtime類的exec()方法調(diào)用平臺shell完成,如windows下的cmd,以及l(fā)inux、unix、macOS下的的shell。
通過Runtime執(zhí)行Python腳本,可以直接通過命令向腳本中傳遞參數(shù),并獲取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總結(jié)
以上兩種方法都可以實現(xiàn)在Java程序中調(diào)用Python腳本,但使用Jython進(jìn)行調(diào)用時,效率較低,也會消耗較多資源,且調(diào)用的腳本需要Python的第三方依賴包時,需要在Jython中安裝第三方包。而使用Runtime調(diào)用腳本時,更多的依賴于運行的平臺,只要當(dāng)前平臺安裝了對應(yīng)的第三方依賴包,腳本就可以順利執(zhí)行,執(zhí)行效率和直接執(zhí)行Python腳本并沒有區(qū)別。
當(dāng)然,在程序中不斷的進(jìn)行嵌套調(diào)用,會降低程序的執(zhí)行效率,增加程序的耦合復(fù)雜度,不方便將來的擴(kuò)展,因此并不建議大家經(jīng)常使用,而可以考慮通過微服務(wù)的方法解決對應(yīng)的問題。
文章還有很多不足之處,希望大家多多交流,多多指教。
參考鏈接
1.五大基于JVM的腳本語言https://coolshell.cn/articles/2631.html
2.Java調(diào)用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
總結(jié)
以上是生活随笔為你收集整理的java 调用python脚本过程_通过Java调用Python脚本的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 求组合数最快方法_Pyth
- 下一篇: python装饰器使用多吗_对于Pyth