IT|軟體|程式語言|Java 調用 Python 使用 Jpython

極少數時候,我們會碰到類似這樣的問題:與A合作寫代碼,A只會寫Python,不熟悉Java,而你只會寫Java不擅長Python,並且發現難以用Java來重寫對方的代碼,這時,就不得不想方設法「調用對方的代碼」。
 
下面舉一些簡單的小例子,借此說明:如何在Java中調用Python代碼。
 
Maven 使用 Jpython
<dependency>
    <groupId>org.python</groupId>
    <artifactId>jython-standalone</artifactId>
    <version>2.7.1</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 or 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編寫的函數
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包中所定義的類獲取、調用這個函數。
 
如果函數需要參數,在Java中必須先將參數轉化為對應的「Python類型」,例如:
__call__(new PyInteger(a), new PyInteger(b))
a,b的類型均為Java中的int型,還有一些Jython類型諸如:PyString(String string)、PyList(Iterator<PyObject> iter)等,詳細信息可以參考官方的api文檔。
 
在本地環境中調用Python腳本
由於Jython運行過慢並且不支持第三方的Python模塊,通過Java代碼執行一段終端命令來調用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把最終結果返回給用戶
 
 
[參考資源]

 
 
 

IT|軟體|開發|Android Studio

簡介

Android Studio是一個 Android 集成開發工具,基於 IntelliJ IDEA.類似Eclipse ADT,Android Studio提供了集成的Android開發工具用於開發和調試。
 
[架構組成]
 
在 IDEA 的基礎上,Android Studio 提供:
基於 Gradle 的構建支持
Android 專屬的重構和快速修復
提示工具以捕獲性能、可用性、版本兼容性等問題
支持 ProGuard 和應用簽名
基於模板的嚮導來生成常用的 Android 應用設計和組件
功能強大的佈局編輯器,可以讓你拖拉 UI 控件並進行效果預覽
 
安裝  Android Studio

[安裝]
 
 
安裝方式2:直接用 Mac OS Homebrew 工具安裝
brew cask install android-studio
 
[初始設定]
 
第一執行時需要做一些設定
一路按下 ”ok“及”next“
 
 
設定 JDK
 
選擇介面風格
 
選擇安裝元件,SDK 一併選起來,不然待會安裝 Android Virtual Device 時會失敗
 
 
按下 Finish 開始下載元件
 
 
[匯入 eclipse 專案]
 
完成初始化設定後,開啟時會跳出下面的畫面,在此選擇 import project
 
選擇匯入的 eclipse 專案路徑,注意不要只選到 workspace 的那一層,要選到專案的目錄
 
匯入時開發工具會做一些 library 處理,預設是全選
 
匯入完成後,有個 summary,提醒開發者 AndroidManifest.xml 等等檔案的位置是不一樣的
 
專案匯入好之後,就可以執行 “Run> Run ‘app’” 模擬器
 
匯出 signed APK
要匯出 signed APK 時,選擇 Build > Generate Signed APK
 
這邊的 Module 目前只有 app 可以選
 
這邊要選擇要 sign 的 key 的路徑與密碼,若在 eclipse 上已經有產生過了,因此直接用就行了
 
選擇產生的 APK 要放在哪個目錄
 
建立好之後,去輸出的目錄裡就可以找到 app-release.apk