中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中如何調用Python

發布時間:2023-05-05 09:12:21 來源:億速云 閱讀:343 作者:zzz 欄目:開發技術

這篇“Java中如何調用Python”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Java中如何調用Python”文章吧。

    Python語言有豐富的系統管理、數據處理、統計類軟件包,因此從java應用中調用Python代碼的需求很常見、實用。DataX 是阿里開源的一個異構數據源離線同步工具,致力于實現包括關系型數據庫(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各種異構數據源之間穩定高效的數據同步功能。Datax也是通過Java調用Python腳本。

    Java core

    Java提供了有兩種方法,分別為ProcessBuilder API和 JSR-223 Scripting Engine。

    使用ProcessBuilder

    通過ProcessBuilder創建本地操作系統進程啟動python并執行Python腳本, hello.py腳本簡單輸出“Hello Python!”。需要開發環境已經安裝了python,并設置了環境變量。

    @Test
    public void givenPythonScript_whenPythonProcessInvoked_thenSuccess() throws Exception {
        ProcessBuilder processBuilder = new ProcessBuilder("python", resolvePythonScriptPath("hello.py"));
        processBuilder.redirectErrorStream(true);
        Process process = processBuilder.start();
        List<String> results = readProcessOutput(process.getInputStream());
        assertThat("Results should not be empty", results, is(not(empty())));
        assertThat("Results should contain output of script: ", results, hasItem(containsString("Hello Python!")));
        int exitCode = process.waitFor();
        assertEquals("No errors should be detected", 0, exitCode);
    }
    private List<String> readProcessOutput(InputStream inputStream) throws IOException {
        try (BufferedReader output = new BufferedReader(new InputStreamReader(inputStream))) {
            return output.lines()
                .collect(Collectors.toList());
        }
    }
    private String resolvePythonScriptPath(String filename) {
        File file = new File("src/test/resources/" + filename);
        return file.getAbsolutePath();
    }

    首先啟動帶一個參數的python命令,參數為python腳本的絕對路徑。可以放在java工程的resources目錄下。需要注意的是:redirectErrorStream(true),為了使得當執行腳本出現錯誤時,錯誤輸出流被合并至標準輸出流。這樣設置可以從Process對象的getInputStream()方法中讀取錯誤信息。如果沒有該設置,則需要分別用兩個方法獲取流:getInputStream() 和 getErrorStream() 。processBuilder.start()獲取Process對象,然后讀取輸出流并驗證結果。

    使用Java腳本引擎

    java6首次引入JSR-223規范,定義一組提供基本腳本功能的腳本API。這些API提供了執行腳本和在Java和腳本語言之間共享值的機制。該規范主要目的是為了統一Java與不同實現JVM的動態腳本語言的交互,Jython是在jvm上運行python的java實現。假設我們在CLASSPATH上有Jython,框架自動發現我們有可能使用該腳本引擎,并允許我們直接請求Python腳本引擎。因為Maven有Jython,我們可以在maven中引用,當然也下載直接安裝:

    <dependency>
        <groupId>org.python</groupId>
        <artifactId>jython</artifactId>
        <version>2.7.2</version>
    </dependency>

    可以通過下面代碼列出所有支持的腳本引擎:

    public static void listEngines() {
        ScriptEngineManager manager = new ScriptEngineManager();
        List<ScriptEngineFactory> engines = manager.getEngineFactories();
        for (ScriptEngineFactory engine : engines) {
            LOGGER.info("Engine name: {}", engine.getEngineName());
            LOGGER.info("Version: {}", engine.getEngineVersion());
            LOGGER.info("Language: {}", engine.getLanguageName());
            LOGGER.info("Short Names:");
            for (String names : engine.getNames()) {
                LOGGER.info(names);
            }
        }
    }

    如果Jython在環境中可用,應該看到相應的輸出:

    ...
    Engine name: jython
    Version: 2.7.2
    Language: python
    Short Names:
    python
    jython

    現在使用Jython調用hello.py腳本:

    @Test
    public void givenPythonScriptEngineIsAvailable_whenScriptInvoked_thenOutputDisplayed() throws Exception {
        StringWriter writer = new StringWriter();
        ScriptContext context = new SimpleScriptContext();
        context.setWriter(writer);
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("python");
        engine.eval(new FileReader(resolvePythonScriptPath("hello.py")), context);
        assertEquals("Should contain script output: ", "Hello Python!", writer.toString().trim());
    }

    使用該API比上面的示例更簡潔。首先設置ScriptContext包含StringWriter,用于保存執行腳本的輸出。然后提供簡稱讓ScriptEngineManager 查找腳本引擎,可以使用python或jython。最后驗證輸出是否與期望一致。

    其實也可以使用PythonInterpretor 類直接調用嵌入的python代碼:

    @Test
    public void givenPythonInterpreter_whenPrintExecuted_thenOutputDisplayed() {
        try (PythonInterpreter pyInterp = new PythonInterpreter()) {
            StringWriter output = new StringWriter();
            pyInterp.setOut(output);
            pyInterp.exec("print('Hello Python!')");
            assertEquals("Should contain script output: ", "Hello Python!", output.toString().trim());
        }
    }

    使用PythonInterpreter類,可以通過exec方法直接執行python代碼。和前面示例一樣通過StringWriter 捕獲執行輸出。下面再看一個示例:

    @Test
    public void givenPythonInterpreter_whenNumbersAdded_thenOutputDisplayed() {
        try (PythonInterpreter pyInterp = new PythonInterpreter()) {
            pyInterp.exec("x = 10+10");
            PyObject x = pyInterp.get("x");
            assertEquals("x: ", 20, x.asInt());
        }
    }

    上面示例可以使用get方法訪問變量值。下面示例看如何捕獲錯誤:

    try (PythonInterpreter pyInterp = new PythonInterpreter()) {
        pyInterp.exec("import syds");
    }

    運行上面代碼會拋出PyException 異常,與在本地執行Python腳本輸出錯誤一樣。

    下面有幾點注意事項:

    • PythonIntepreter 實現了AutoCloseable,最好與 try-with-resources 一起使用。

    • PythonIntepreter類名不是表示Python代碼的解析器,Python程序在Jython是運行在jvm中,執行前需要編譯為java字節碼。

    • 盡管Jython是Java的Python實現,但它可能不包含與本機Python相同的所有子包。

    下面示例展示如何把java變量賦給Python變量:

    import org.python.util.PythonInterpreter; 
    import org.python.core.*; 
    class test3{
        public static void main(String a[]){
            int number1 = 10;
            int number2 = 32;
            try (PythonInterpreter pyInterp = new PythonInterpreter()) {
                python.set("number1", new PyInteger(number1));
                python.set("number2", new PyInteger(number2));
                python.exec("number3 = number1+number2");
                PyObject number3 = python.get("number3");
                System.out.println("val : "+number3.toString());
            }
        }
    }

    以上就是關于“Java中如何調用Python”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    宜良县| 绵阳市| 石阡县| 古蔺县| 台东县| 康保县| 岑巩县| 平凉市| 三河市| 开鲁县| 专栏| 汽车| 青川县| 寻乌县| 灵武市| 高唐县| 临漳县| 会泽县| 乌海市| 永昌县| 比如县| 黑龙江省| 昭苏县| 阿拉善左旗| 汉沽区| 洛阳市| 安宁市| 班玛县| 商南县| 乌鲁木齐市| 顺昌县| 古田县| 辉县市| 青岛市| 怀宁县| 建德市| 万年县| 西青区| 若羌县| 安仁县| 运城市|