天天看點

java調python代碼_在Java中調用Python代碼

極少數時候,我們會碰到類似這樣的問題:與A同學合作寫代碼, A同學隻會寫Python,不熟悉Java ,而你隻會寫Java不擅長Python,并且發現難以用Java來重寫對方的代碼,這時,就不得不想方設法“調用對方的代碼”。

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

什麼是Jython?

Jython(原JPython),可以了解為一個由Java語言編寫的Python解釋器。

要使用Jython,隻需要将Jython-x.x.x.jar檔案置于classpath中即可 --> 官網下載下傳

當然,通過Maven導入也OK,如下:

org.python

jython-standalone

2.7.0

一個HelloPython程式

importorg.python.util.PythonInterpreter;public classHelloPython {public static voidmain(String[] args) {

PythonInterpreter interpreter= newPythonInterpreter();

interpreter.exec("print('hello')");

}

}

什麼是PythonInterpreter呢?它的中文意思即“Python解釋器”。我們知道Python程式都是由解釋器執行的,上面的代碼在JVM中建立一個“Python解釋器”對象,用于模拟Python解釋器的行為,并通過exec("Python語句") 直接在JVM中執行Python代碼,代碼的輸出結果為:hello。該程式運作速度相較正常的Java或者Python程式都要慢那麼一點。

在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代碼:

defhello():return 'Hello'

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

importorg.python.core.PyFunction;importorg.python.core.PyObject;importorg.python.util.PythonInterpreter;public classHelloPython {public static voidmain(String[] args) {

PythonInterpreter interpreter= newPythonInterpreter();

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類型諸如:PyString、

在本地環境中調用Python腳本

例子程式(與舍友合作寫的一個手寫識别程式,可識别很粗的數字,JAVA寫界面,Python識别):

import java.io.*;classPyCaller {private static final String DATA_SWAP = "temp.txt";private static final String PY_URL = System.getProperty("user.dir") + "\\test.py";public static voidwriteImagePath(String path) {

PrintWriter pw= null;try{

pw= new PrintWriter(new FileWriter(newFile(DATA_SWAP)));

}catch(IOException e) {

e.printStackTrace();

}

pw.print(path);

pw.close();

}public staticString readAnswer() {

BufferedReader br;

String answer= null;try{

br= new BufferedReader(new FileReader(newFile(DATA_SWAP)));

answer=br.readLine();

}catch(FileNotFoundException e) {

e.printStackTrace();

}catch(IOException e) {

e.printStackTrace();

}returnanswer;

}public static voidexecPy() {

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) throwsIOException, InterruptedException {

writeImagePath("D:\\labs\\mytest\\test.jpg");

execPy();

System.out.println(readAnswer());

}

}

運作流程:Java Swing 界面接收使用者輸入 --> Java 将使用者輸入寫到本地檔案中 --> Java 調用本地 Python 腳本 --> Python 從本地檔案拿到使用者輸入 --> Python 處理使用者輸入得到最終結果 --> Python 把最終結果寫到本地檔案 --> Java 對 Python 腳本的調用結束 --> Java 從本地檔案中取出最終結果 --> Java 把最終結果傳回給使用者