Rumah  >  Artikel  >  Java  >  Bagaimana untuk memanggil Python di Java

Bagaimana untuk memanggil Python di Java

WBOY
WBOYke hadapan
2023-05-17 12:08:122221semak imbas

    Bahasa Python mempunyai banyak pengurusan sistem, pemprosesan data dan pakej perisian statistik, jadi keperluan untuk memanggil kod Python daripada aplikasi Java adalah sangat biasa dan praktikal. DataX ialah alat penyegerakan luar talian untuk sumber data heterogen sumber terbuka oleh Alibaba Ia khusus untuk mencapai data yang stabil dan cekap antara pelbagai sumber data heterogen termasuk pangkalan data hubungan (MySQL, Oracle, dll.), HDFS, Hive, ODPS, HBase, FTP. , dsb. Fungsi penyegerakan. Datax juga memanggil skrip Python melalui Java.

    Java core

    Java menyediakan dua kaedah iaitu ProcessBuilder API dan JSR-223 Scripting Engine.

    Gunakan ProcessBuilder

    Buat proses sistem pengendalian tempatan melalui ProcessBuilder untuk memulakan python dan laksanakan skrip Python Skrip hello.py hanya mengeluarkan "Hello Python!". Persekitaran pembangunan perlu dipasang python dan pembolehubah persekitaran ditetapkan.

    @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();
    }

    Untuk menulis semula ayat ini anda boleh berkata: Mula menggunakan arahan Python dengan satu hujah, iaitu laluan penuh kepada skrip Python. Ia boleh diletakkan dalam direktori sumber projek java. Apa yang perlu diberi perhatian ialah: redirectErrorStream(true), untuk membuat aliran keluaran ralat digabungkan ke dalam aliran keluaran standard apabila ralat berlaku semasa melaksanakan skrip. Maklumat ralat boleh dibaca dengan memanggil kaedah getInputStream() objek Proses. Tanpa tetapan ini, anda perlu menggunakan dua kaedah untuk mendapatkan strim: getInputStream() dan getErrorStream(). Selepas mendapat objek Proses daripada ProcessBuilder, sahkan keputusan dengan membaca aliran output.

    Menggunakan Enjin Skrip Java

    Spesifikasi JSR-223 mula diperkenalkan dalam Java 6, yang mentakrifkan satu set API skrip yang boleh menyediakan kefungsian skrip asas. API ini menyediakan mekanisme untuk berkongsi nilai dan melaksanakan skrip antara Java dan bahasa skrip. Tujuan utama spesifikasi ini adalah untuk menyatukan interaksi antara Java dan bahasa skrip dinamik yang melaksanakan JVM berbeza Jython ialah pelaksanaan Java Python yang berjalan pada JVM. Dengan mengandaikan kami mempunyai Jython pada CLASSPATH, rangka kerja secara automatik mendapati bahawa kami mempunyai kemungkinan untuk menggunakan enjin skrip tersebut dan membolehkan kami meminta enjin skrip Python secara langsung. Di Maven, kami boleh merujuk Jython, atau memuat turun dan memasangnya terus

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

    Anda boleh menyenaraikan semua enjin skrip yang disokong melalui kod berikut:

    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);
            }
        }
    }

    Jika Jython tersedia dalam persekitaran, anda harus lihat Output yang sepadan:

    ...
    Nama enjin: jython
    Versi: 2.7.2
    Bahasa: python
    Nama Pendek:
    python
    jython

    Sekarang panggil skrip hello.py menggunakan Jython:

    @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());
    }

    Menggunakan API ini lebih ringkas daripada contoh di atas. Apabila menetapkan ScriptContext, anda perlu memasukkan StringWriter untuk menyimpan output pelaksanaan skrip. Kemudian berikan nama pendek untuk membenarkan ScriptEngineManager mencari enjin skrip, yang boleh menggunakan python atau jython. Akhir sekali, sahkan bahawa output adalah konsisten dengan jangkaan.

    Malah, anda juga boleh menggunakan kelas PythonInterpretor untuk memanggil terus kod python terbenam:

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

    Kaedah exec yang disediakan oleh kelas PythonInterpreter boleh terus melaksanakan kod Python. Tangkap output pelaksanaan melalui StringWriter seperti dalam contoh sebelumnya. Mari lihat contoh lain:

    @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());
        }
    }

    Contoh di atas boleh menggunakan kaedah get untuk mengakses nilai pembolehubah. Contoh berikut menunjukkan cara menangkap ralat:

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

    Menjalankan kod di atas akan membuang pengecualian PyException, yang sama seperti melaksanakan skrip Python secara setempat untuk mengeluarkan ralat.

    Berikut ialah beberapa perkara yang perlu diberi perhatian:

    • PythonIntepreter melaksanakan AutoCloseable, yang paling sesuai digunakan dengan cuba-dengan-sumber.

    • Nama kelas PythonIntepreter bukan penghurai yang mewakili program Python yang dijalankan dalam Jython dalam jvm dan perlu disusun ke dalam kod bait java sebelum pelaksanaan.

    • Walaupun Jython ialah pelaksanaan Python bagi Java, ia mungkin tidak mengandungi semua subpakej yang sama seperti Python asli.

    Contoh berikut menunjukkan cara untuk menetapkan pembolehubah java kepada pembolehubah 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());
            }
        }
    }

    Atas ialah kandungan terperinci Bagaimana untuk memanggil Python di Java. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    Kenyataan:
    Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam