Risposte:
Jython: Python per la piattaforma Java - http://www.jython.org/index.html
Puoi facilmente chiamare le funzioni python dal codice Java con Jython. Questo è fintanto che il tuo codice python stesso gira sotto jython, cioè non usa alcune estensioni c che non sono supportate.
Se per te funziona, è sicuramente la soluzione più semplice che puoi ottenere. Altrimenti puoi utilizzare org.python.util.PythonInterpreter
dal nuovo supporto interprete Java6.
Un semplice esempio dalla cima della mia testa, ma spero dovrebbe funzionare: (nessun controllo degli errori fatto per brevità)
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec("import sys\nsys.path.append('pathToModules if they are not there by default')\nimport yourModule");
// execute a function that takes a string and returns a string
PyObject someFunc = interpreter.get("funcName");
PyObject result = someFunc.__call__(new PyString("Test!"));
String realResult = (String) result.__tojava__(String.class);
Ehi, pensavo di inserire la mia risposta anche se è tardi. Penso che ci siano alcune cose importanti da considerare prima di quanto forte desideri avere il collegamento tra java e python.
In primo luogo, vuoi solo chiamare le funzioni o vuoi effettivamente che il codice Python cambi i dati nei tuoi oggetti java? Questo è molto importante. Se vuoi solo chiamare del codice python con o senza argomenti, non è molto difficile. Se i tuoi argomenti sono primitivi, è ancora più facile. Tuttavia, se si desidera che la classe java implementi le funzioni membro in python, che modificano i dati dell'oggetto java, allora non è così facile o diretto.
In secondo luogo stiamo parlando di cpython o lo farà jython? Direi che cpython è dove si trova! Direi che questo è il motivo per cui Python è così stupido! Avendo astrazioni così elevate, tuttavia, accedi a c, c ++ quando necessario. Immagina di poterlo avere in java. Questa domanda non vale nemmeno la pena chiedersi se jython è ok perché è comunque facile.
Quindi ho giocato con i seguenti metodi e li ho elencati da facili a difficili:
Da Java a Jython
Vantaggi: banalmente facile. Avere riferimenti effettivi agli oggetti Java
Svantaggi: nessun CPython, estremamente lento!
Jython di java è così facile, e se questo è davvero sufficiente, allora fantastico. Tuttavia è molto lento e non cpython! Vale la pena vivere la vita senza cpython non credo! Puoi facilmente avere codice Python che implementa le tue funzioni membro per gli oggetti java.
Da Java a Jython a CPython tramite Pyro
Pyro è il modulo oggetto remoto per python. Hai un oggetto su un interprete cpython e puoi inviargli oggetti che vengono trasferiti tramite serializzazione e può anche restituire oggetti tramite questo metodo. Nota che se invii un oggetto python serializzato da jython e poi chiami alcune funzioni che modificano i dati nei suoi membri, allora non vedrai quei cambiamenti in java. Devi solo ricordarti di rispedire i dati che desideri da pyro. Questo credo sia il modo più semplice per accedere a cpython! Non hai bisogno di jni o jna o swig o .... Non hai bisogno di conoscere c o c ++. kool eh?
Vantaggi: accesso a cpython, non difficile come i seguenti metodi
Svantaggi: non è possibile modificare i dati dei membri degli oggetti java direttamente da python. È in qualche modo indiretto, (jython è l'uomo medio).
Da Java a C / C ++ tramite JNI / JNA / SWIG a Python tramite interprete incorporato (magari usando le librerie BOOST?)
OMG questo metodo non è per i deboli di cuore. E posso dirti che mi ci è voluto molto tempo per ottenere questo risultato con un metodo decente. Il motivo principale per cui vorresti farlo è che puoi eseguire codice cpython che funge da pieno controllo sul tuo oggetto java. Ci sono cose importanti da considerare prima di decidere di provare a fare il pane java (che è come uno scimpanzé) con Python (che è come un cavallo). In primo luogo se si blocca l'interprete che si spegne per il programma! E non farmi iniziare con i problemi di concorrenza! Inoltre, c'è un lotto di caldaia, credo di aver trovato la configurazione migliore per ridurre al minimo questa caldaia, ma è comunque assegnato! Quindi, come procedere: considera che C ++ è il tuo intermediario, i tuoi oggetti sono in realtà oggetti C ++! Bene che tu lo sappia ora. Scrivi semplicemente il tuo oggetto come se il tuo programma come in cpp non java, con i dati a cui desideri accedere da entrambi i mondi. Quindi puoi usare il generatore di wrapper chiamato swig (http://www.swig.org/Doc1.3/Java.html ) per renderlo accessibile a java e compilare una dll che chiami System.load (nome dll qui) in java. Prima fallo funzionare, poi passa alla parte difficile! Per arrivare a Python devi incorporare un interprete. In primo luogo io suggerisco di fare alcuni programmi interprete ciao o questo tutorial Embedding Python in C / C . Una volta che hai funzionato, è tempo di far ballare il cavallo e la scimmia! Puoi inviare un oggetto c ++ a Python tramite [boost] [3]. So di non averti dato il pesce, ti ho semplicemente detto dove trovarlo. Alcuni suggerimenti da notare per questo durante la compilazione.
Quando compili Boost, dovrai compilare una libreria condivisa. E devi includere e collegare le cose che ti servono da jdk, cioè jawt.lib, jvm.lib, (avrai anche bisogno del client jvm.dll nel tuo percorso quando avvii l'applicazione) così come il python27.lib o qualunque e il boost_python-vc100-mt-1_55.lib. Quindi includi Python / include, jdk / include, boost e usa solo librerie condivise (dll) altrimenti boost ha un effetto lacrimoso. E sì, lo so. Ci sono tanti modi in cui questo può diventare aspro. Quindi assicurati di fare ogni cosa blocco per blocco. Quindi mettili insieme.
Non è intelligente avere codice Python all'interno di java. Avvolgi il tuo codice Python con flask o altro framework web per renderlo un microservizio. Rendi il tuo programma java in grado di chiamare questo microservizio (ad esempio tramite REST).
Credimi, è molto semplice e ti farà risparmiare un sacco di problemi. E i codici sono vagamente accoppiati in modo che siano scalabili.
Aggiornato il 24 marzo 2020: secondo il commento di @ stx, l'approccio di cui sopra non è adatto per il trasferimento massiccio di dati tra client e server. Ecco un altro approccio che ho consigliato: collegare Python e Java con Rust (anche C / C ++ ok). https://medium.com/@shmulikamar/https-medium-com-shmulikamar-connecting-python-and-java-with-rust-11c256a1dfb0
Molte delle risposte menzionano che è possibile utilizzare JNI o JNA per accedere a cpython, ma non consiglierei di iniziare da zero perché esistono già librerie open source per l'accesso a cpython da java. Per esempio:
Ecco una libreria che ti consente di scrivere i tuoi script python una volta e di decidere quale metodo di integrazione (Jython, CPython / PyPy tramite Jep e Py4j) utilizzare in fase di runtime:
https://github.com/subes/invesdwin-context-python
Poiché ogni metodo ha i suoi vantaggi / svantaggi, come spiegato nel link.
Dipende da cosa intendi per funzioni Python? se fossero scritti in cpython non puoi chiamarli direttamente dovrai usare JNI , ma se fossero scritti in Jython puoi chiamarli facilmente da java, poiché jython alla fine genera codice java byte.
Ora, quando dico scritto in cpython o jython non ha molto senso perché python è python e la maggior parte del codice verrà eseguito su entrambe le implementazioni a meno che non si utilizzino librerie specifiche che si basano su cpython o java.
GraalVM è una buona scelta. Ho combinato Java + Javascript con GraalVM per la progettazione di microservizi (Java con riflessione Javascript). Recentemente hanno aggiunto il supporto per Python, proverei soprattutto con quanto è diventata grande la sua comunità nel corso degli anni.
Puoi chiamare qualsiasi lingua da Java utilizzando Java Native Interface
Jython ha alcune limitazioni:
Ci sono molte differenze. Innanzitutto, i programmi Jython non possono utilizzare moduli di estensione CPython scritti in C. Questi moduli di solito hanno file con estensione .so, .pyd o .dll. Se vuoi usare un tale modulo, dovresti cercare un equivalente scritto in puro Python o Java. Sebbene sia tecnicamente fattibile supportare tali estensioni - IronPython lo fa - non ci sono piani per farlo in Jython.
Distribuire i miei script Python come file JAR con Jython?
puoi semplicemente chiamare script python (o bash o script Perl) da Java utilizzando Runtime o ProcessBuilder e passare l'output a Java:
Esecuzione di uno script di shell bash in java
Esecuzione della riga di comando in Java
java runtime.getruntime () riceve l'output dall'esecuzione di un programma a riga di comando
Questo fornisce una buona panoramica delle opzioni attuali. Alcuni dei quali sono nominati in altre risposte. Jython non è utilizzabile finché non decidono di implementare Python 3.x e molti degli altri progetti stanno arrivando dal lato python e vogliono accedere a java. Ma ci sono ancora alcune opzioni, per nominare qualcosa che non è stato ancora nominato: gRPC