Ako volať Python z Javy

1. Prehľad

Python je čoraz populárnejším programovacím jazykom, najmä vo vedeckej komunite, vďaka bohatej palete numerických a štatistických balíkov. Nie je preto nezvyčajnou požiadavkou na vyvolanie kódu Pythonu z našich aplikácií Java.

V tomto návode pozrieme sa na niektoré z najbežnejších spôsobov volania kódu Python z Javy.

2. Jednoduchý skript v jazyku Python

V celom tomto výučbe budeme používať veľmi jednoduchý skript v jazyku Python, ktorý si zadefinujeme vo vyhradenom súbore s názvom ahoj.py:

tlač („Ahoj čitatelia Baeldungu !!“)

Za predpokladu, že máme fungujúcu inštaláciu Pythonu, mali by sme pri spustení nášho skriptu vidieť vytlačenú správu:

$ python hello.py Ahoj čitatelia Baeldungu !!

3. Jadro Java

V tejto časti sa pozrieme na dve rôzne možnosti, ktoré môžeme použiť na vyvolanie nášho skriptu Python pomocou jadra Java.

3.1. Použitím ProcessBuilder

Poďme sa najskôr pozrieť na to, ako môžeme použiť ProcessBuilder API na vytvorenie procesu natívneho operačného systému, ktorý sa má spustiť pytón a vykonajte náš jednoduchý skript:

@ Test public void givenPythonScript_whenPythonProcessInvoked_thenSuccess () vyvolá výnimku {ProcessBuilder processBuilder = nový ProcessBuilder ("python", resolvePythonScriptPath ("hello.py")); processBuilder.redirectErrorStream (true); Proces proces = processBuilder.start (); Zoznam výsledkov = readProcessOutput (process.getInputStream ()); assertThat ("Výsledky by nemali byť prázdne", výsledky, sú (nie (prázdne ()))); assertThat ("Výsledky by mali obsahovať výstup skriptu:", results, hasItem (containsString ("Hello Baeldung Readers !!"))); int exitCode = process.waitFor (); assertEquals ("Nemali by sa zistiť žiadne chyby", 0, exitCode); }

V tomto prvom príklade používame program pytón príkaz s jedným argumentom, ktorý je absolútnou cestou k nášmu ahoj.py scenár. Nájdeme to v našom test / zdroje priečinok.

Ak to zhrnieme, vytvárame naše ProcessBuilder objekt odovzdávajúci hodnoty príkazu a argumentu konštruktoru. Je tiež dôležité spomenúť výzvu na číslo redirectErrorStream (true). V prípade akýchkoľvek chýb bude chybový výstup zlúčený so štandardným výstupom.

Je to užitočné, pretože to znamená, že keď zavoláme, môžeme čítať chybové správy z príslušného výstupu getInputStream () metóda na Proces objekt. Ak túto vlastnosť nenastavíme na pravda, potom budeme musieť načítať výstup z dvoch samostatných tokov pomocou príkazu getInputStream () a getErrorStream () metódy.

Teraz začneme proces pomocou štart () metóda na získanie a Proces objekt. Potom si prečítame výstup procesu a overíme, či obsah obsahuje to, čo očakávame.

Ako už bolo spomenuté vyššie, vytvorili sme predpoklad, že pytón príkaz je k dispozícii prostredníctvom CESTA premenná.

3.2. Práca s skriptovacím motorom JSR-223

JSR-223, ktorý bol prvýkrát predstavený v prostredí Java 6, definuje množinu skriptovacích API, ktoré poskytujú základné funkcie skriptovania. Tieto metódy poskytujú mechanizmy na vykonávanie skriptov a na zdieľanie hodnôt medzi Javou a skriptovacím jazykom. Hlavným cieľom tejto normy bolo pokúsiť sa o zabezpečenie určitej jednotnosti pri spolupráci s rôznymi skriptovacími jazykmi z jazyka Java.

Môžeme použiť zásuvnú architektúru skriptového jadra pre akýkoľvek dynamický jazyk, ak má samozrejme implementáciu JVM. Jython je implementácia platformy Python na platforme Java, ktorá beží na JVM.

Za predpokladu, že máme na serveri Jython CLASSPATHrámec by mal automaticky zistiť, že máme možnosť tento skriptovací nástroj používať, a umožniť nám priamo požiadať o skriptovací stroj Python.

Pretože Jython je dostupný z Maven Central, môžeme ho jednoducho zahrnúť do nášho pom.xml:

 org.python jython 2.7.2 

Rovnako sa dá tiež priamo stiahnuť a nainštalovať.

Uveďme zoznam všetkých skriptovacích nástrojov, ktoré máme k dispozícii:

ScriptEngineManagerUtils.listEngines ();

Ak máme možnosť použiť Jython, mali by sme vidieť zobrazený príslušný skriptovací engine:

... Názov motora: jython Verzia: 2.7.2 Jazyk: python Krátke mená: python jython 

Teraz, keď vieme, že môžeme používať skriptovací modul Jython, poďme ďalej a uvidíme, ako nazvať náš ahoj.py scenár:

@Test public void givenPythonScriptEngineIsAvailable_whenScriptInvoked_thenOutputDisplayed () vyvolá výnimku {StringWriter writer = new StringWriter (); ScriptContext context = nový SimpleScriptContext (); context.setWriter (spisovateľ); ScriptEngineManager manager = nový ScriptEngineManager (); ScriptEngine engine = manager.getEngineByName ("python"); engine.eval (nový FileReader (resolvePythonScriptPath ("hello.py")), kontext); assertEquals ("Mal by obsahovať výstup skriptu:", "Hello Baeldung Readers !!", writer.toString (). trim ()); }

Ako vidíme, práca s týmto API je celkom jednoduchá. Najskôr začneme nastavením a ScriptContext ktorý obsahuje a StringWriter. Toto sa použije na uloženie výstupu zo skriptu, ktorý chceme vyvolať.

Potom použijeme getEngineByName metóda ScriptEngineManager triedy vyhľadať a vytvoriť ScriptEngine pre dané krátke meno. V našom prípade môžeme prejsť pytón alebo jython čo sú dva krátke názvy spojené s týmto motorom.

Rovnako ako predtým, posledným krokom je získať výstup z nášho skriptu a skontrolovať, či sa zhoduje s tým, čo sme očakávali.

4. Jython

Pokračovaním v Jythone máme tiež možnosť vloženia kódu Pythonu priamo do nášho kódu Java. Môžeme to urobiť pomocou PythonInterpretor trieda:

@Test public void givenPythonInterpreter_whenPrintExecuted_thenOutputDisplayed () {try (PythonInterpreter pyInterp = new PythonInterpreter ()) {StringWriter output = new StringWriter (); pyInterp.setOut (výstup); pyInterp.exec ("print ('Hello Baeldung Readers !!')"); assertEquals ("Mal by obsahovať výstup skriptu:", "Hello Baeldung Readers !!", output.toString () .trim ()); }}

Pomocou PythonInterpreter trieda nám umožňuje vykonať reťazec zdrojového kódu Pythonu cez vykon metóda. Rovnako ako predtým používame a StringWriter na zachytenie výstupu z tohto vykonania.

Teraz si ukážeme príklad, keď sčítame dve čísla:

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

V tomto príklade vidíme, ako môžeme použiť dostať metóda prístupu k hodnote premennej.

V našom poslednom príklade Jython uvidíme, čo sa stane, keď dôjde k chybe:

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

Keď spustíme tento kód a PyException je vyhodená a uvidíme rovnakú chybu, ako keby sme pracovali s natívnym Pythonom:

Traceback (posledný hovor posledný): Súbor „“, riadok 1, v ImportError: Žiadny modul s názvom syds

Niekoľko vecí, ktoré by sme si mali uvedomiť:

  • Ako PythonIntepreter náradie Automatické uzatváranie, je dobré používať vyskúšajte zdroje pri práci s touto triedou
  • The PythonInterpreter názov triedy neznamená, že je náš kód Pythonu interpretovaný. Programy Pythonu v Jythone sú prevádzkované JVM, a preto sú pred vykonaním kompilované do bajtkódu Java
  • Aj keď je Jython implementáciou Pythonu pre Javu, nemusí obsahovať všetky rovnaké čiastkové balíky ako natívny Python

5. Apache Commons Exec

Ďalšou knižnicou tretích strán, ktorú by sme mohli zvážiť pri použití, je Apache Common Exec, ktorá sa pokúša prekonať niektoré nedostatky Java Process API.

The Commons-Exec artefakt je dostupný z Maven Central:

 org.apache.commons commons-exec 1.3 

Teraz poďme, ako môžeme túto knižnicu používať:

@Test public void givenPythonScript_whenPythonProcessExecuted_thenSuccess () hodí ExecuteException, IOException {String line = "python" + resolvePythonScriptPath ("hello.py"); CommandLine cmdLine = CommandLine.parse (riadok); ByteArrayOutputStream outputStream = nový ByteArrayOutputStream (); PumpStreamHandler streamHandler = nový PumpStreamHandler (outputStream); DefaultExecutor Exekútor = nový DefaultExecutor (); executor.setStreamHandler (streamHandler); int exitCode = executor.execute (cmdLine); assertEquals ("Nemali by sa zistiť žiadne chyby", 0, exitCode); assertEquals ("Mal by obsahovať výstup skriptu:", "Hello Baeldung Readers !!", outputStream.toString () .trim ()); }

Tento príklad nie je príliš nepodobný nášmu prvému použitému príkladu ProcessBuilder. Vytvárame a Príkazový riadok objekt pre náš zadaný príkaz. Ďalej sme nastavili obslužný program toku, ktorý sa má použiť na zachytenie výstupu z nášho procesu pred vykonaním nášho príkazu.

Ak to zhrnieme, hlavnou filozofiou tejto knižnice je ponúknuť balík na vykonávanie procesov zameraný na podporu širokej škály operačných systémov prostredníctvom konzistentného API.

6. Využitie protokolu HTTP na interoperabilitu

Vráťme sa na chvíľu o krok späť a namiesto pokusu o vyvolanie Pythonu priamo zvážme použitie dobre zavedeného protokolu, ako je HTTP, ako abstrakčnej vrstvy medzi dvoma rôznymi jazykmi.

V skutočnosti je Python dodávaný s jednoduchým zabudovaným serverom HTTP, ktorý môžeme použiť na zdieľanie obsahu alebo súborov cez HTTP:

python -m http.server 9000

Ak teraz pôjdeme na // localhost: 9000, uvidíme obsah uvedený v adresári, kde sme spustili predchádzajúci príkaz.

Niektoré ďalšie populárne rámce, ktoré by sme mohli zvážiť na použitie pri vytváraní robustnejších webových služieb alebo aplikácií založených na Pythone, sú Flask a Django.

Keď máme koncový bod, ku ktorému máme prístup, môžeme na vyvolanie implementácie našej webovej služby / aplikácie v Pythone použiť ktorúkoľvek z niekoľkých knižníc Java HTTP.

7. Záver

V tomto tutoriáli sme sa dozvedeli o niektorých najpopulárnejších technológiách pre volanie kódu Pythonu z Javy.

Celý zdrojový kód článku je ako vždy k dispozícii na GitHub.


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