在java中調用執行python代碼(一)

極少數時候,咱們會碰到相似這樣的問題:與A同窗合做寫代碼, A同窗只會寫Python,不熟悉Java ,而你只會寫Java不擅長Python,而且發現難以用Java來重寫對方的代碼,這時,就不得不千方百計「調用對方的代碼」。html

下面,我就經過一些簡單的小例子來講明:如何在Java中調用Python代碼。java

什麼是Jython? 

Jython(原JPython),能夠理解爲一個由Java語言編寫的Python解釋器。git

要使用Jython,只須要將Jython-x.x.x.jar文件置於classpath中便可 --> 官網下載百度網盤github

固然,經過Maven導入也OK,以下:小程序

<dependency> <groupId>org.python</groupId> <artifactId>jython-standalone</artifactId> <version>2.7.0</version> </dependency>

 

一個HelloPython程序

import org.python.util.PythonInterpreter; public class HelloPython { public static void main(String[] args) { PythonInterpreter interpreter = new PythonInterpreter(); interpreter.exec("print('hello')"); } }

什麼是PythonInterpreter呢?它的中文意思即「Python解釋器」。咱們知道Python程序都是由解釋器執行的,上面的代碼在JVM中建立一個「Python解釋器」對象,用於模擬Python解釋器的行爲,並經過exec("Python語句") 直接在JVM中執行Python代碼,代碼的輸出結果爲:hello。該程序運行速度相較正常的Java或者Python程序都要慢那麼一點。mybatis

 

在JVM中執行Python腳本

interpreter.execfile("D:/labs/mytest/hello.py"); 

如上,將exec改成execfile就能夠了。須要注意的是,這個 .py文件不能含有第三方模塊,由於這個「Python腳本」說到底還是在JVM環境下執行的(而非依賴於本地計算機環境),若是 .py 程序中包含有第三方模塊(例如 NumPy)將會在編譯期報錯:java ImportError: No module named xxx函數

 

在JVM中調用Python編寫的函數

先寫一個hello.py的Python代碼:post

def hello(): return 'Hello'

在Java代碼中調用這個Python函數:測試

import org.python.core.PyFunction; import org.python.core.PyObject; import org.python.util.PythonInterpreter; public class HelloPython { public static void main(String[] args) { PythonInterpreter interpreter = new PythonInterpreter(); interpreter.execfile("D:/labs/hello.py"); PyFunction pyFunction = interpreter.get("hello", PyFunction.class); // 第一個參數爲指望得到的函數(變量)的名字,第二個參數爲指望返回的對象類型 PyObject pyObject = pyFunction.__call__(); // 調用函數  System.out.println(pyObject); } }

上面的代碼執行結果爲:Hello

能夠發現:即使只是調用一個函數,也必須先加載整個 .py文件,以後才能經過Jython包中所定義的類獲取、調用這個函數。

若是Python函數須要參數,必須先將Java代碼中的參數轉化爲對應的「Python類型」(姑且能夠稱做 Jython 類型 (●'◡'●),例如:

__call__(new PyInteger(a), new PyInteger(b))

a,b的類型均爲Java中的int型,還有一些Jython類型諸如:PyStringPyList,詳細信息能夠參考官方的API文檔。

 

在本地環境中調用Python腳本

因爲Jython運行過慢而且不支持第三方的Python模塊,經過Java代碼執行一段終端(或者RPC)命令來調用Python腳本可能纔是實際中真正會用到的方式。

下面是和舍友合做寫的一個小程序(能夠識別很粗的手寫數字),界面上引用了core java裏的一段代碼:

import java.io.*; class PyCaller { private static final String DATA_SWAP = "temp.txt"; private static final String PY_URL = System.getProperty("user.dir") + "\\test.py"; public static void writeImagePath(String path) { PrintWriter pw = null; try { pw = new PrintWriter(new FileWriter(new File(DATA_SWAP))); } catch (IOException e) { e.printStackTrace(); } pw.print(path); pw.close(); } public static String readAnswer() { BufferedReader br; String answer = null; try { br = new BufferedReader(new FileReader(new File(DATA_SWAP))); answer = br.readLine(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return answer; } public static void execPy() { Process proc = null; try { proc = Runtime.getRuntime().exec("python " + PY_URL); proc.waitFor(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } // 測試碼 public static void main(String[] args) throws IOException, InterruptedException {  writeImagePath("D:\\labs\\mytest\\test.jpg"); execPy(); System.out.println(readAnswer()); } }

運行流程:Java Swing 界面接收用戶輸入 --> Java 將用戶輸入寫到本地文件中 --> Java 調用本地 Python 腳本 --> Python 從本地文件拿到用戶輸入 --> Python 處理用戶輸入獲得最終結果 --> Python 把最終結果寫到本地文件 --> Java 對 Python 腳本的調用結束 --> Java 從本地文件中取出最終結果 --> Java 把最終結果返回給用戶

完整代碼連接:http://pan.baidu.com/s/1sl4l68H 

相關文章
相關標籤/搜索