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?
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?
Réponses:
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.PythonInterpreter
le 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);
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.
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
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.
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.
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.
Vous pouvez appeler n'importe quelle langue depuis java à l'aide de l'interface native Java
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
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