通過Java調用Python腳本


 

在進行開發的過程中,偶爾會遇到需要使用Java調用Python腳本的時候,畢竟Python在諸如爬蟲,以及科學計算等方面具有天然的優勢。最近在工作中遇到需要在Java程序中調用已經寫好的Python程序,故做一下記錄。

1常用的Java調用Python腳本的兩種方式

調用方式通常為以下兩種:

•通過Jython調用,即通過Jython.jar提供的類庫實現

•直接通過Java的Runtime實現,Runtime類的Runtime.getRuntime()開啟進程,執行python腳本文件

2通過Jython實現調用

Jython簡介

Jython主頁:http://www.jython.org/

Jython是Python語言在Java平台的實現,本質上,Jython是由Java編寫,其是在JVM上實現的Python語言。因此,可以直接通過Jython在Java中調用Python。

Jython安裝

在安裝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語句

在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");

}

}

  • 在Java中執行已經編寫好的名為xxx.py的 Python腳本

直接通過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.getRuntime().exec()實現調用

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM