Chiamare Python in Java?


Risposte:


101

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.PythonInterpreterdal 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);

Ho installato JYthon, o presumo di averlo fatto, e continuo a provare a eseguire il codice che hai delineato ma è evidenziato come un errore. L'installazione di Jython deve andare in una cartella specifica, nelle cartelle python o java?
Shahab

2
Non ci sono errori, sto solo avendo difficoltà a integrare Jython in Netbeans
Shahab

Se non ci sono errori funzionerebbe, quindi ovviamente non è così;) "Errore" non significa errore di runtime, potrebbe essere anche un errore di compilazione.
Voo

Colpa mia, è stato un cattivo uso della parola. Stavo cercando di aggiungere jython.jar al mio progetto e netbeans. L'ho capito però
Shahab

1
La fine del ciclo di vita di Python 2 è l'1.1.2020 e Jython supporta solo Python 2.7. quindi nessun Jython è praticamente morto. L'opzione migliore (la più semplice) è Jep lib
garyee,

63

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.


2
Ecco una libreria che ti consente di scrivere i tuoi script python una volta e di decidere quale metodo di integrazione (Jython, CPython tramite Jep e Py4j) usare in fase di esecuzione: github.com/subes/invesdwin-context-python Poiché ogni metodo ha i suoi vantaggi / svantaggi
Sottomette il

@subes quel progetto sembra fantastico L'ho scritto qualche tempo fa. Ti incoraggio a scrivere una risposta, la voterei a favore. Non mi piace la risposta migliore haha ​​perché non penso che fornisca molte informazioni utili al di fuori di una ricerca su Google.
Snickers3192

Ho creato una risposta separata
sottometti il

3
questa risposta ha l'odore di "questa dovrebbe essere la risposta accettata" o sono solo io? ;-)
Mauricio Gracia Gutierrez

18

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


+1, ma per quanto riguarda le prestazioni aggiuntive e il sovraccarico di comunicazione della creazione e dell'analisi dei messaggi avanti e indietro su entrambe le estremità?
stx

sì, questo deve definire un'interfaccia API con input / output minimo richiesto. Non è intelligente trasferire molti dati tra client / server sulla rete. Se non è possibile definire una tale interfaccia, questo approccio progettuale non è adatto.
Peiming Hu il

10

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:


8

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.


Questo progetto non ha alcuna versione.
Christian Schlichtherle

@ChristianSchlichtherle invesdwin-context-python versione 1.0.0 non è disponibile; grazie a questo piccolo gioiello: github.com/loewenfels/dep-graph-releaser
subes

6

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.

vedi qui come usare l'interprete Python in Java.


5

A seconda dei requisiti, potrebbero essere utili opzioni come XML-RPC , che può essere utilizzato per chiamare in remoto funzioni virtualmente in qualsiasi linguaggio che supporti il ​​protocollo.


5

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.


4

Puoi chiamare qualsiasi lingua da Java utilizzando Java Native Interface


6
Qualsiasi linguaggio che a sua volta può essere chiamato da c, cioè. Bene, python può farlo, ma Jython è una soluzione molto più semplice in realtà (o usando PyInterpreter in j6 +). Non è così banale scrivere il codice per chiamare le funzioni python da c.
Voo

2

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


0

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.