128 Stimmen

Ruft Python in Java auf?

Ich frage mich, ob es möglich ist, Python-Funktionen von Java-Code aus mit Jython aufzurufen, oder ob es nur dafür gedacht ist, Java-Code von Python aus aufzurufen?

108voto

Voo Punkte 27974

Jython: Python für die Java-Plattform - http://www.jython.org/index.html

Sie können Python-Funktionen ganz einfach aus Java-Code mit Jython aufrufen. Vorausgesetzt, dass Ihr Python-Code selbst unter Jython läuft, d.h. er verwendet keine c-Erweiterungen, die nicht unterstützt werden.

Wenn das für Sie funktioniert, ist es sicherlich die einfachste Lösung, die Sie bekommen können. Andernfalls können Sie org.python.util.PythonInterpreter aus der neuen Java6-Interpreterunterstützung verwenden.

Ein einfaches Beispiel aus dem Stegreif - aber sollte hoffentlich funktionieren: (keine Fehlerüberprüfung für Kürze durchgeführt)

PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec("import sys\nsys.path.append('pathToModules, wenn sie nicht standardmäßig vorhanden sind')\nimport IhreModule");
// Führen Sie eine Funktion aus, die einen String entgegennimmt und einen String zurückgibt
PyObject someFunc = interpreter.get("funcName");
PyObject result = someFunc.__call__(new PyString("Test!"));
String realResult = (String) result.__tojava__(String.class);

Ab 2021 unterstützt Jython kein Python 3.x

71voto

Derrops Punkte 6823

Ich denke, es gibt einige wichtige Dinge zu beachten, bevor Sie sich darüber Gedanken machen, wie stark Sie die Verbindung zwischen Java und Python haben möchten.

Zum einen Möchten Sie nur Funktionen aufrufen oder möchten Sie tatsächlich, dass Python-Code die Daten in Ihren Java-Objekten ändert? Das ist sehr wichtig. Wenn Sie nur etwas Python-Code mit oder ohne Argumente aufrufen möchten, ist das nicht sehr schwierig. Wenn Ihre Argumente primitiv sind, wird es noch einfacher. Wenn Sie jedoch möchten, dass eine Java-Klasse Methoden in Python implementiert, die die Daten des Java-Objekts ändern, ist dies nicht so einfach oder geradlinig.

Zum anderen, sprechen wir von CPython oder reicht Jython aus? Ich würde sagen, CPython ist der Ort, an dem es passiert! Ich würde dafür plädieren, dass Python so cool ist! So hohe Abstraktionen haben jedoch Zugang zu C,C++, wenn nötig. Stellen Sie sich vor, wenn Sie das in Java hätten. Diese Frage ist nicht einmal wert, wenn Jython in Ordnung ist, weil es dann ohnehin einfach ist.

Also habe ich mit den folgenden Methoden gespielt und sie von einfach bis schwierig aufgelistet:

Java zu Jython

Vorteile: Trivial einfach. Tatsächliche Verweise auf Java-Objekte haben

Nachteile: Kein CPython, extrem langsam!

Jython aus Java heraus ist so einfach, und wenn das wirklich ausreicht, dann ist das großartig. Es ist jedoch sehr langsam und es gibt kein CPython! Ist das Leben lebenswert ohne CPython, glaube ich nicht! Sie können ganz einfach Python-Code haben, der Ihre Methodenfunktionen für Ihre Java-Objekte implementiert.

Java zu Jython zu CPython über Pyro

Pyro ist das Remote-Objektmodul für Python. Sie haben ein Objekt auf einem CPython-Interpreter und können ihm Objekte senden, die über Serialisierung übertragen werden, und es kann auch Objekte auf diese Weise zurückgeben. Beachten Sie, dass wenn Sie ein serialisiertes Python-Objekt von Jython aus senden und dann einige Funktionen aufrufen, die die Daten in seinen Mitgliedern ändern, dann sehen Sie diese Änderungen nicht in Java. Sie müssen nur daran denken, die Daten zurückzusenden, die Sie von Pyro haben möchten. Ich glaube, dass dies der einfachste Weg ist, zu CPython zu gelangen! Sie benötigen kein JNI oder JNA oder SWIG oder.... Sie müssen kein C oder C++ kennen, cool, oder?

Vorteile: Zugriff auf CPython, nicht so schwierig wie die folgenden Methoden

Nachteile: Kann die Mitgliedsdaten von Java-Objekten nicht direkt von Python aus ändern. Ist etwas indirekt (Jython ist der Mittelsmann).

Java zu C/C++ via JNI/JNA/SWIG zu Python über eingebetteten Interpreter (vielleicht unter Verwendung der BOOST-Bibliotheken?)

OMG diese Methode ist nichts für schwache Nerven. Und ich kann Ihnen sagen, dass es sehr lange gedauert hat, um dies mit einer anständigen Methode zu erreichen. Der Hauptgrund, warum Sie dies tun möchten, ist, damit Sie CPython-Code ausführen können, der volle Kontrolle über Ihr Java-Objekt hat. Es gibt wichtige Dinge, die Sie beachten müssen, bevor Sie versuchen, Java (das wie ein Schimpanse ist) mit Python (das wie ein Pferd ist) zu vermischen. Erstens, wenn der Interpreter abstürzt, ist für Ihr Programm Schluss! Und fangen Sie mich erst gar nicht mit den Problemen der Nebenläufigkeit an! Außerdem gibt es eine Menge Boilerplate-Code, ich glaube, ich habe die beste Konfiguration gefunden, um diesen Boilerplate-Code zu minimieren, aber dennoch ist es viel! Also wie gehen Sie vor: Denken Sie daran, dass C++ Ihr Vermittler ist, Ihre Objekte sind tatsächlich C++-Objekte! Gut, dass Sie das jetzt wissen. Schreiben Sie einfach Ihr Objekt, als ob Ihr Programm in C++ und nicht in Java wäre, mit den Daten, auf die Sie aus beiden Welten zugreifen möchten. Dann können Sie den Wrapper-Generator namens SWIG verwenden (http://www.swig.org/Doc1.3/Java.html), um auf diese Weise auf Java zuzugreifen, und eine DLL kompilieren, die Sie in Java mit System.load(DLL-Name hier) aufrufen. Bekommen Sie dies zuerst zum Laufen, dann gehen Sie zum schwierigen Teil über! Um zu Python zu gelangen, müssen Sie einen Interpreter einbetten. Zuerst schlage ich vor, einige Hallo-Welt-Interpreter-Programme zu machen oder dieses Tutorial Embedding python in C/C. Wenn Sie damit funktionieren, ist es Zeit für Pferd und Affe, zusammen tanzen zu lassen! Sie können Ihr C++-Objekt an Python über [boost][3] senden. Ich weiß, ich habe Ihnen nicht den Fisch gegeben, sondern Ihnen nur gesagt, wo der Fisch zu finden ist. Einige Punkte, die Sie beim Kompilieren beachten sollten.

Wenn Sie Boost kompilieren, müssen Sie eine gemeinsame Bibliothek kompilieren. Und Sie müssen das einbeziehen und zu den Dingen verlinken, die Sie aus dem JDK benötigen, d. h. jawt.lib, jvm.lib, (Sie benötigen auch die client jvm.dll in Ihrem Pfad, wenn Sie die Anwendung starten) sowie die python27.lib oder was auch immer und die boost_python-vc100-mt-1_55.lib. Dann fügen Sie Python/include, jdk/include, boost hinzu und verwenden nur freigegebene Bibliotheken (DLLs), da sonst Boost nervös wird. Und ja, das ist wirklich intensiv. Es gibt so viele Wege, auf denen das schiefgehen kann. Also stellen Sie sicher, dass Sie jedes Ding blockweise erledigen. Und dann setzen Sie alles zusammen.

26voto

Peiming Hu Punkte 497

Es ist nicht klug, Python-Code innerhalb von Java zu haben. Verpacken Sie Ihren Python-Code mit Flask oder einem anderen Web-Framework, um ihn zu einem Microservice zu machen. Dadurch kann Ihr Java-Programm diesen Microservice aufrufen (z.B. über REST).

Dieser Ansatz ist einfach und wird Ihnen eine Menge Probleme ersparen. Und die Codes sind locker gekoppelt, so dass sie skalierbar sind.

Aktualisiert am 24. März 2020: Laut dem Kommentar von @stx ist der obige Ansatz nicht für den massiven Datentransfer zwischen Client und Server geeignet. Hier ist ein anderer Ansatz, den ich empfehle: Verbinden von Python und Java mit Rust (C/C++ ist auch in Ordnung). https://medium.com/@shmulikamar/https-medium-com-shmulikamar-connecting-python-and-java-with-rust-11c256a1dfb0

12voto

bsteffen Punkte 371

Einige der Antworten erwähnen, dass Sie JNI oder JNA verwenden können, um auf cpython zuzugreifen, aber ich würde nicht empfehlen, von Grund auf neu zu beginnen, weil es bereits Open-Source-Bibliotheken gibt, um auf cpython von Java aus zuzugreifen. Zum Beispiel:

10voto

Wildhammer Punkte 1786

GraalVM ist eine gute Wahl. Ich habe die Kombination von Java+Javascript mit GraalVM für das Design von Mikroservices gemacht (Java mit Javascript-Reflektion). Sie haben kürzlich Unterstützung für Python hinzugefügt, ich würde es auf jeden Fall ausprobieren, besonders mit dem großen Wachstum seiner Community im Laufe der Jahre.

UPDATE Juni 2021

https://www.graalvm.org/reference-manual/python/ sagt

GraalVM stellt eine Python 3.8-kompatible Laufzeitumgebung bereit. Ein Hauptziel der GraalVM Python-Laufzeitumgebung ist die Unterstützung von SciPy und seinen Bestandteilen sowie die Arbeit mit anderen Datenwissenschafts- und Maschinenlern-Bibliotheken aus dem reichhaltigen Python-Ökosystem. Zu diesem Zeitpunkt wird die Python-Laufzeitumgebung für Experimente und neugierige Endbenutzer zur Verfügung gestellt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X