Vous appelez Python en Java?

117

Je me demande s'il est possible d'appeler des fonctions python à partir de code java en utilisant jython, ou est-ce uniquement pour appeler du code java à partir de python?

Shahab
la source
3
Veuillez jeter un oeil sur une question similaire et lire la réponse. bytes.com/topic/python/answers/…
AlexR

Réponses:

101

Jython: Python pour la plateforme Java - http://www.jython.org/index.html

Vous pouvez facilement appeler des fonctions python à partir du code Java avec Jython. C'est aussi longtemps que votre code python lui-même s'exécute sous jython, c'est-à-dire qu'il n'utilise pas certaines extensions c qui ne sont pas prises en charge.

Si cela fonctionne pour vous, c'est certainement la solution la plus simple que vous puissiez obtenir. Sinon, vous pouvez utiliser org.python.util.PythonInterpreterle nouveau support de l'interpréteur Java6.

Un exemple simple du haut de ma tête - mais devrait fonctionner j'espère: (aucune vérification d'erreur n'est effectuée par souci de concision)

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);
Voo
la source
J'ai installé JYthon, ou je suppose que je l'ai fait, et je continue d'essayer d'exécuter le code que vous avez décrit mais il a été mis en évidence comme une erreur. L'installation de Jython doit-elle aller dans un dossier spécifique, soit dans les dossiers python ou java?
Shahab
2
Il n'y a pas d'erreur, j'ai juste du mal à intégrer Jython dans Netbeans
Shahab
S'il n'y a pas d'erreur, cela fonctionnerait, donc ce n'est évidemment pas le cas;) "Erreur" ne signifie pas une erreur d'exécution, peut également être une erreur de compilation.
Voo le
Mon mauvais, c'était une mauvaise utilisation du mot. J'essayais d'ajouter le jython.jar à mon projet et à netbeans. Je l'ai compris
Shahab
1
La fin de vie de Python 2 est le 1.1.2020 et Jython ne prend en charge que Python 2.7. donc aucun Jython n'est fondamentalement mort. La meilleure option (la plus simple) est la
bibliothèque
63

Hé, je pensais que j'entrerais ma réponse à cela même si c'est tard. Je pense qu'il y a des choses importantes à considérer d'abord avec la force avec laquelle vous souhaitez avoir le lien entre java et python.

d'abord Voulez-vous seulement appeler des fonctions ou voulez-vous réellement que le code Python modifie les données de vos objets Java? C'est très important. Si vous souhaitez uniquement appeler du code python avec ou sans arguments, ce n'est pas très difficile. Si vos arguments sont primitifs, cela rend les choses encore plus faciles. Cependant, si vous voulez que la classe java implémente des fonctions membres en python, qui modifient les données de l'objet java, alors ce n'est pas si facile ou simple.

Deuxièmement, parlons-nous de cpython ou est-ce que jython le fera? Je dirais que cpython est là où il en est! Je recommanderais que c'est pourquoi python est si kool! Avoir des abstractions aussi élevées mais accéder à c, c ++ en cas de besoin. Imaginez si vous pouviez avoir cela en java. Cette question ne vaut même pas la peine de se demander si jython est correct car alors c'est facile de toute façon.

J'ai donc joué avec les méthodes suivantes et les ai répertoriées de facile à difficile:

Java vers Jython

Avantages: Trively facile. Avoir des références réelles à des objets Java

Inconvénients: pas de CPython, extrêmement lent!

Jython de java est si simple, et si cela suffit vraiment, tant mieux. Cependant c'est très lent et pas de cpython! La vie vaut-elle la peine d'être vécue sans cpython, je ne pense pas! Vous pouvez facilement avoir du code python implémentant vos fonctions membres pour vos objets java.

Java vers Jython vers CPython via Pyro

Pyro est le module objet distant pour python. Vous avez un objet sur un interpréteur cpython, et vous pouvez lui envoyer des objets qui sont transférés via la sérialisation et il peut également renvoyer des objets via cette méthode. Notez que si vous envoyez un objet python sérialisé à partir de jython et que vous appelez ensuite certaines fonctions qui modifient les données de ses membres, vous ne verrez pas ces modifications dans java. Vous devez juste vous rappeler de renvoyer les données que vous voulez de pyro. Je pense que c'est le moyen le plus simple d'accéder à cpython! Vous n'avez pas besoin de jni ou jna ou swig ou .... Vous n'avez pas besoin de connaître de c ou c ++. kool hein?

Avantages: accès à cpython, pas aussi difficile que les méthodes suivantes

Inconvénients: impossible de modifier les données membres des objets Java directement à partir de python. Est quelque peu indirect, (jython est un intermédiaire).

Java vers C / C ++ via JNI / JNA / SWIG vers Python via un interpréteur intégré (peut-être en utilisant les bibliothèques BOOST?)

OMG cette méthode n'est pas pour les faibles de cœur. Et je peux vous dire qu'il m'a fallu très longtemps pour y parvenir avec une méthode décente. La principale raison pour laquelle vous voudriez faire cela est que vous puissiez exécuter du code cpython qui contrôle pleinement votre objet java. Il y a des choses importantes à considérer avant de décider d'essayer de pain java (qui est comme un chimpanzé) avec du python (qui est comme un cheval). Premièrement, si vous plantez l'interpréteur qui est éteint pour votre programme! Et ne me lancez pas sur les problèmes de concurrence! De plus, il y a allot de chaudière, je crois avoir trouvé la meilleure configuration pour minimiser cette chaudière mais quand même c'est allot! Alors, comment s'y prendre: Considérez que C ++ est votre intermédiaire, vos objets sont en fait des objets C ++! C'est bien que vous le sachiez maintenant. Écrivez simplement votre objet comme si votre programme était en cpp et non en java, avec les données auxquelles vous souhaitez accéder depuis les deux mondes. Ensuite, vous pouvez utiliser le générateur de wrapper appelé swig (http://www.swig.org/Doc1.3/Java.html ) pour le rendre accessible à java et compiler une dll que vous appelez System.load (nom de la dll ici) en java. Faites en sorte que cela fonctionne d'abord, puis passez à la partie la plus difficile! Pour accéder à python, vous devez intégrer un interpréteur. Tout d' abord , je suggère de faire des programmes d'interprétation bonjour ou ce tutoriel python Embedding en C / C . Une fois que cela fonctionne, il est temps de faire danser le cheval et le singe! Vous pouvez vous envoyer un objet C ++ vers python via [boost] [3]. Je sais que je ne vous ai pas donné le poisson, je vous ai simplement dit où trouver le poisson. Quelques pointeurs à noter lors de la compilation.

Lorsque vous compilez boost, vous devrez compiler une bibliothèque partagée. Et vous devez inclure et lier les éléments dont vous avez besoin à partir de jdk, c'est-à-dire jawt.lib, jvm.lib, (vous aurez également besoin du client jvm.dll dans votre chemin lors du lancement de l'application) ainsi que python27.lib ou peu importe et le boost_python-vc100-mt-1_55.lib. Ensuite, incluez Python / include, jdk / include, boost et n'utilisez que des bibliothèques partagées (dll), sinon boost a un larmoiement. Et ouais plein de je sais. Il y a tellement de façons dont cela peut mal tourner. Assurez-vous donc de faire chaque chose bloc par bloc. Ensuite, rassemblez-les.

Snickers3192
la source
2
Voici une bibliothèque qui vous permet d'écrire vos scripts python une fois et de décider quelle méthode d'intégration (Jython, CPython via Jep et Py4j) à utiliser au moment de l'exécution: github.com/subes/invesdwin-context-python puisque chaque méthode a ses propres avantages / inconvénients
subes
@subes ce projet a l'air génial J'ai écrit ceci il y a un moment. Je vous encourage à écrire une réponse que j'apprécierais. Je n'aime pas la réponse principale haha ​​parce que je ne pense pas qu'elle fournit beaucoup d'informations utiles en dehors d'une recherche Google.
Snickers3192
J'ai créé une réponse séparée
subes
3
cette réponse sent-elle "ceci devrait être la réponse acceptée" ou est-ce juste moi? ;-)
Mauricio Gracia Gutierrez
18

Ce n'est pas intelligent d'avoir du code python dans java. Enveloppez votre code python avec flask ou un autre framework Web pour en faire un microservice. Rendez votre programme java capable d'appeler ce microservice (par exemple via REST).

Croyez-moi, c'est très simple et vous évitera des tonnes de problèmes. Et les codes sont faiblement couplés, donc ils sont évolutifs.

Mise à jour le 24 mars 2020: selon le commentaire de @ stx, l'approche ci-dessus n'est pas adaptée au transfert de données massif entre le client et le serveur. Voici une autre approche que j'ai recommandée: Connecter Python et Java avec Rust (C / C ++ également ok). https://medium.com/@shmulikamar/https-medium-com-shmulikamar-connecting-python-and-java-with-rust-11c256a1dfb0

Peiming Hu
la source
+1, mais qu'en est-il des performances supplémentaires et des frais de communication liés à la création et à l'analyse des messages dans les deux sens des deux côtés?
stx
oui, cela doit définir une interface api avec un minimum d'entrée / sortie requis. Il n'est pas judicieux d'avoir beaucoup de transfert de données entre client / serveur sur le réseau. Si vous ne pouvez pas définir une telle interface, cette approche de conception ne convient pas.
Peiming Hu
10

Plusieurs des réponses mentionnent que vous pouvez utiliser JNI ou JNA pour accéder à cpython mais je ne recommanderais pas de partir de zéro car il existe déjà des bibliothèques open source pour accéder à cpython à partir de java. Par exemple:

Bsteffen
la source
8

Voici une bibliothèque qui vous permet d'écrire vos scripts python une fois et de décider quelle méthode d'intégration (Jython, CPython / PyPy via Jep et Py4j) à utiliser lors de l'exécution:

https://github.com/subes/invesdwin-context-python

Étant donné que chaque méthode a ses propres avantages / inconvénients, comme expliqué dans le lien.

sous-marins
la source
Ce projet n'a pas de version.
Christian Schlichtherle
@ChristianSchlichtherle invesdwin-context-python version 1.0.0 n'est pas disponible; grâce à ce petit bijou: github.com/loewenfels/dep-graph-releaser
subes
6

Cela dépend de ce que vous entendez par fonctions python? s'ils ont été écrits en cpython, vous ne pouvez pas les appeler directement, vous devrez utiliser JNI , mais s'ils ont été écrits en Jython, vous pouvez facilement les appeler depuis java, car jython génère finalement du code d'octet java.

Maintenant, quand je dis écrit en cpython ou jython, cela n'a pas beaucoup de sens car python est python et la plupart du code fonctionnera sur les deux implémentations à moins que vous n'utilisiez des bibliothèques spécifiques qui reposent sur cpython ou java.

voir ici comment utiliser l'interpréteur Python en Java.

Anurag Uniyal
la source
5

Selon vos besoins, des options telles que XML-RPC peuvent être utiles, qui peuvent être utilisées pour appeler à distance des fonctions pratiquement dans n'importe quel langage prenant en charge le protocole.

Timo
la source
5

GraalVM est un bon choix. J'ai fait une combinaison Java + Javascript avec GraalVM pour la conception de microservices (Java avec réflexion Javascript). Ils ont récemment ajouté le support pour python, je lui donnerais un essai, surtout avec la taille de sa communauté au fil des ans.

Marteau sauvage
la source
4

Vous pouvez appeler n'importe quelle langue depuis java à l'aide de l'interface native Java

nidhin
la source
6
Tout langage qui lui-même peut être appelé à partir de c qui est. Bon ok python peut, mais Jython est une solution beaucoup plus simple là-bas vraiment (ou en utilisant le PyInterpreter dans j6 +). Ce n'est pas si simple d'écrire le code pour appeler des fonctions python à partir de c.
Voo le
2

Jython a quelques limitations:

Il existe un certain nombre de différences. Premièrement, les programmes Jython ne peuvent pas utiliser les modules d'extension CPython écrits en C. Ces modules ont généralement des fichiers avec l'extension .so, .pyd ou .dll. Si vous souhaitez utiliser un tel module, vous devez rechercher un équivalent écrit en pur Python ou Java. Bien qu'il soit techniquement possible de prendre en charge de telles extensions - IronPython le fait - il n'est pas prévu de le faire dans Jython.

Distribuer mes scripts Python sous forme de fichiers JAR avec Jython?

vous pouvez simplement appeler des scripts python (ou des scripts bash ou Perl) depuis Java à l'aide de Runtime ou ProcessBuilder et renvoyer la sortie à Java:

Exécution d'un script shell bash en java

Exécution de la ligne de commande en Java

java runtime.getruntime () obtenant la sortie de l'exécution d'un programme en ligne de commande

Alex
la source
0

Cela donne un assez bon aperçu des options actuelles. Certains d'entre eux sont nommés dans d'autres réponses. Jython n'est pas utilisable jusqu'à ce qu'ils décident d'implémenter Python 3.x et de nombreux autres projets viennent du côté python et veulent accéder à java. Mais il y a encore quelques options, pour nommer quelque chose qui n'a pas encore été nommé: gRPC

Garyee
la source