Hogyan hívhatunk Python-ot Java-ról

1. Áttekintés

A Python egyre népszerűbb programozási nyelv, különösen a tudományos közösségben a numerikus és statisztikai csomagok gazdag változatossága miatt. Ezért nem szokatlan követelmény a Python-kód meghívása a Java-alkalmazásainkból.

Ebben az oktatóanyagban megnézzük a Python kód Java-ból történő hívásának néhány leggyakoribb módját.

2. Egyszerű Python szkript

A bemutató során egy nagyon egyszerű Python szkriptet fogunk használni, amelyet egy dedikált fájlban definiálunk hello.py:

nyomtatás ("Hello Baeldung olvasók !!")

Ha feltételezzük, hogy működik egy Python telepítés, akkor a szkript futtatásakor látni kell az üzenetet:

$ python hello.py Helló Baeldung olvasók !!

3. Core Java

Ebben a szakaszban két különböző lehetőséget veszünk szemügyre, amelyek segítségével a Java Java segítségével meghívhatjuk a Python szkriptünket.

3.1. Használata ProcessBuilder

Először vessünk egy pillantást arra, hogyan használhatjuk a ProcessBuilder API egy natív operációs rendszer elindításához piton és hajtsa végre egyszerű szkriptünket:

@Test public void givenPythonScript_whenPythonProcessInvoked_thenSuccess () dobja a Kivételt {ProcessBuilder processBuilder = new ProcessBuilder ("python", ResolPythonScriptPath ("hello.py")); processBuilder.redirectErrorStream (true); Process process = processBuilder.start (); Eredmények felsorolása = readProcessOutput (process.getInputStream ()); assertThat ("Az eredmények nem lehetnek üresek", az eredmények (nem (üres ()))); assertThat ("Az eredményeknek tartalmazniuk kell a szkript kimenetét:", results, hasItem (tartalmazString ("Helló Baeldung olvasók !!"))); int exitCode = process.waitFor (); assertEquals ("Nem szabad hibát észlelni", 0, exitCode); }

Ebben az első példában a piton parancsot egy argumentummal, amely a mi abszolút utunk hello.py forgatókönyv. Megtalálhatjuk a mi teszt / források mappába.

Összefoglalva: létrehozzuk a sajátunkat ProcessBuilder objektum átadja a parancsot és az argumentum értékeket a konstruktornak. Fontos megemlíteni a hívást is redirectErrorStream (true). Bármilyen hiba esetén a hiba kimenet összeolvad a standard kimenettel.

Ez hasznos, mivel azt jelenti, hogy a megfelelő kimenetről bármilyen hibaüzenetet kiolvashatunk, amikor meghívjuk a getInputStream () módszer a Folyamat tárgy. Ha nem állítjuk be ezt a tulajdonságot igaz, akkor le kell olvasnunk két különálló adatfolyam kimenetét a getInputStream () és a getErrorStream () mód.

Most elindítjuk a folyamatot a Rajt() módszer a Folyamat tárgy. Ezután elolvassuk a folyamat kimenetét, és ellenőrizzük, hogy a tartalom elvárható-e.

Mint korábban említettük, feltételeztük, hogy a piton parancs a PÁLYA változó.

3.2. Munka a JSR-223 parancsfájlmotorral

A JSR-223, amelyet először a Java 6-ban vezettek be, meghatározza a parancsfájlok alapfunkcióit biztosító szkript API-k készletét. Ezek a módszerek biztosítják a parancsfájlok végrehajtásának mechanizmusait, valamint az értékek megosztását a Java és a szkriptnyelv között. A szabvány fő célja az volt, hogy megpróbáljon valamilyen egységességet teremteni a Java különböző szkriptnyelveivel való együttműködésben.

Bármely dinamikus nyelvhez használhatjuk a beépíthető szkriptmotor-architektúrát, feltéve, hogy természetesen rendelkezik JVM-implementációval. A Jython a Python Java platform implementációja, amely a JVM-en fut.

Feltéve, hogy a Jython van a CLASSPATH, a keretrendszernek automatikusan fel kell fedeznie, hogy lehetőségünk van ennek a szkriptmotornak a használatára, és lehetővé kell tennie, hogy közvetlenül a Python szkriptmotort kérjük.

Mivel a Jython elérhető a Maven Central-tól, egyszerűen felvehetjük a mi pom.xml:

 org.python jython 2.7.2 

Hasonlóképpen, közvetlenül is letölthető és telepíthető.

Soroljuk fel az összes rendelkezésünkre álló szkriptmotort:

ScriptEngineManagerUtils.listEngines ();

Ha lehetőségünk van a Jython használatára, meg kell jelenítenünk a megfelelő parancsfájlmotort:

... A motor neve: jython Verzió: 2.7.2 Nyelv: python Rövid nevek: python jython 

Most, hogy tudjuk, hogy használhatjuk a Jython parancsfájlmotort, menjünk előre, és nézzük meg, hogyan hívhatjuk a sajátunkat hello.py forgatókönyv:

@Test public void givenPythonScriptEngineIsAvailable_whenScriptInvoked_thenOutputDisplayed () dobja a Kivételt {StringWriter író = új StringWriter (); ScriptContext context = új SimpleScriptContext (); context.setWriter (író); ScriptEngineManager manager = új ScriptEngineManager (); ScriptEngine motor = manager.getEngineByName ("python"); engine.eval (új FileReader (resolutionPythonScriptPath ("hello.py")), kontextus); assertEquals ("Szkript kimenetet kell tartalmaznia:", "Helló Baeldung olvasók !!", író.toString (). trim ()); }

Mint láthatjuk, nagyon egyszerű ezzel az API-val dolgozni. Először az a ScriptContext amely tartalmazza a StringWriter. Ezt fogjuk használni a meghívni kívánt szkript kimenetének tárolására.

Ezután használjuk a getEngineByName módszere ScriptEngineManager osztályban felkutatni és létrehozni a ScriptEngine adott rövid névre. Esetünkben átmehetünk piton vagy jython amelyek a motorhoz társított két rövid név.

Az előző lépéshez hasonlóan az utolsó lépés az, hogy megszerezzük a szkript kimenetét, és ellenőrizzük, hogy az megfelel-e annak, amire számítottunk.

4. Jython

A Jython folytatásával lehetőségünk van Python kód beágyazására is közvetlenül a Java kódunkba. Ezt megtehetjük a PythonInterpretor osztály:

@Test public void givenPythonInterpreter_whenPrintExecuted_thenOutputDisplayed () {try (PythonInterpreter pyInterp = new PythonInterpreter ()) {StringWriter output = new StringWriter (); pyInterp.setOut (output); pyInterp.exec ("print ('Helló Baeldung olvasók !!')"); assertEquals ("Tartalmaznia kell a szkript kimenetét:", "Helló Baeldung olvasók !!", output.toString () .trim ()); }}

Használni a PythonInterpreter osztály lehetővé teszi számunkra a Python forráskód sztring végrehajtását a exec módszer. Mint korábban, a StringWriter hogy megragadja a végrehajtás kimenetét.

Most nézzünk meg egy példát, ahol két számot adunk össze:

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

Ebben a példában láthatjuk, hogyan használhatjuk a kap metódus segítségével elérheti a változó értékét.

Utolsó Jython példánkban meglátjuk, mi történik, ha hiba lép fel:

try (PythonInterpreter pyInterp = új PythonInterpreter ()) {pyInterp.exec ("sydd importálása"); }

Amikor ezt a kódot futtatjuk a PyException dobásra kerül, és ugyanazt a hibát fogjuk látni, mintha natív Python-nal dolgoznánk:

Traceback (a legutóbbi hívás utoljára): "" fájl, 1. sor, az ImportError fájlban: Nincs syds nevű modul

Néhány pontot meg kell jegyeznünk:

  • Mint PythonIntepreter megvalósítja Automatikusan zárható, jó gyakorlat használni erőforrásokkal próbálkozzon amikor ezzel az osztállyal dolgozik
  • A PythonInterpreter Az osztály neve nem jelenti azt, hogy a Python kódunkat értelmezzük. A Jythonban található Python programokat a JVM futtatja, ezért a végrehajtás előtt Java bytecode-ba fordítják
  • Bár a Jython a Java Python-implementációja, előfordulhat, hogy nem tartalmazza az összes olyan alcsomagot, mint a natív Python

5. Apache Commons Exec

Egy másik harmadik fél könyvtár, amelynek használatát fontolóra vehetjük, az Apache Common Exec, amely megpróbálja kiküszöbölni a Java Process API néhány hiányosságát.

A commons-exec műtárgy elérhető a Maven Central-tól:

 org.apache.commons commons-exec 1.3 

Most nézzük meg, hogyan tudjuk használni ezt a könyvtárat:

@Test public void givenPythonScript_whenPythonProcessExecuted_thenSuccess () dobja az ExecuteException, IOException {String line = "python" + ResolPythonScriptPath ("hello.py"); CommandLine cmdLine = CommandLine.parse (sor); ByteArrayOutputStream outputStream = új ByteArrayOutputStream (); PumpStreamHandler streamHandler = új PumpStreamHandler (outputStream); DefaultExecutor végrehajtó = new DefaultExecutor (); végrehajtó.setStreamHandler (streamHandler); int exitCode = végrehajtó.execute (cmdLine); assertEquals ("Nem szabad hibát észlelni", 0, exitCode); assertEquals ("Szkript kimenetet kell tartalmaznia:", "Helló Baeldung olvasók !!", outputStream.toString () .trim ()); }

Ez a példa nem túl különbözik az első példánktól ProcessBuilder. Létrehozunk egy Parancs sor objektum a megadott parancsunkra. Ezután beállítottunk egy adatfolyam-kezelőt, amely a folyamat kimenetének rögzítésére szolgál, mielőtt végrehajtanánk a parancsunkat.

Összefoglalva, a könyvtár fő filozófiája az, hogy olyan folyamat végrehajtási csomagot kínál, amelynek célja az operációs rendszerek széles körének támogatása egy következetes API-n keresztül.

6. A HTTP használata az interoperabilitáshoz

Tegyünk egy lépést egy pillanatra, és ahelyett, hogy megpróbálnánk a Python-ot közvetlenül meghívni, fontolóra vegyük egy jól bejáratott protokoll, például a HTTP, mint absztrakciós réteg használatát a két különböző nyelv között.

Valójában a Python egy egyszerű beépített HTTP szerverrel szállít, amelyet tartalmak vagy fájlok HTTP-n keresztüli megosztására használhatunk:

python -m http.szerver 9000

Ha most elmegyünk // localhost: 9000, látni fogjuk annak a könyvtárnak a tartalmát, ahol az előző parancsot elindítottuk.

Néhány más népszerű keretrendszer, amelyet fontolóra vehetünk a robusztusabb Python-alapú webszolgáltatások vagy alkalmazások létrehozásához, a Flask és a Django.

Miután rendelkezünk egy végponttal, amelyhez hozzáférhetünk, a több Java HTTP könyvtár bármelyikét felhasználhatjuk a Python webszolgáltatás / alkalmazás megvalósításunk meghívására.

7. Következtetés

Ebben az oktatóanyagban megismerkedtünk a Python kód Java-ból történő hívásának legnépszerűbb technológiáival.

Mint mindig, a cikk teljes forráskódja elérhető a GitHubon.


$config[zx-auto] not found$config[zx-overlay] not found