Python in Java aufrufen?


116

Ich frage mich, ob es möglich ist, Python-Funktionen mit Java-Code aus Java-Code aufzurufen, oder ob Java-Code nur aus Python aufgerufen werden kann.


3
Bitte werfen Sie einen Blick auf eine ähnliche Frage und lesen Sie die Antwort. bytes.com/topic/python/answers/…
AlexR

Antworten:


100

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

Mit Jython können Sie Python-Funktionen einfach aus Java-Code aufrufen. Das heißt, solange Ihr Python-Code selbst unter Jython ausgeführt wird, dh einige C-Erweiterungen, die nicht unterstützt werden, werden nicht verwendet.

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.PythonInterpreterdie neue Java6-Interpreter-Unterstützung verwenden.

Ein einfaches Beispiel von oben - sollte aber funktionieren, hoffe ich: (keine Fehlerprüfung auf Kürze durchgeführt)

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

Ich habe JYthon installiert, oder ich nehme an, ich habe es getan, und ich versuche weiterhin, den von Ihnen beschriebenen Code auszuführen, der jedoch als Fehler hervorgehoben wurde. Muss die Installation von Jython in einen bestimmten Ordner verschoben werden, entweder in den Python- oder Java-Ordnern?
Shahab

2
Es gibt keinen Fehler, es fällt mir nur schwer, Jython in Netbeans zu integrieren
Shahab

Wenn es keinen Fehler gibt, würde es funktionieren, also ist das offensichtlich nicht der Fall;) "Fehler" bedeutet nicht Laufzeitfehler, könnte auch ein Kompilierungsfehler sein.
Voo

Mein schlechtes, es war eine schlechte Verwendung des Wortes. Ich habe versucht, die Datei jython.jar zu meinem Projekt und meinen Netbeans hinzuzufügen. Ich habe es aber herausgefunden
Shahab

1
Python 2 End of Life ist 1.1.2020 und Jython unterstützt nur Python 2.7. Also ist kein Jython im Grunde tot. Beste (einfachste) Option ist der Jep lib
garyee

62

Hey, ich dachte, ich würde meine Antwort darauf eingeben, obwohl es spät ist. Ich denke, es gibt einige wichtige Dinge, die Sie zuerst berücksichtigen sollten, um festzustellen, wie stark Sie die Verbindung zwischen Java und Python wünschen.

zuerst möchten Sie nur Funktionen aufrufen oder möchten Sie tatsächlich, dass Python-Code die Daten in Ihren Java-Objekten ändert? Dies ist sehr wichtig. Wenn Sie nur Python-Code mit oder ohne Argumente aufrufen möchten, ist dies nicht sehr schwierig. Wenn Ihre Argumente primitiv sind, wird es noch einfacher. Wenn Sie jedoch möchten, dass die Java-Klasse Mitgliedsfunktionen in Python implementiert, die die Daten des Java-Objekts ändern, ist dies nicht so einfach oder unkompliziert.

Zweitens sprechen wir über Cpython oder wird Jython dies tun? Ich würde sagen, Cpython ist dort, wo es ist! Ich würde befürworten, dass Python deshalb so cool ist! Mit solch hohen Abstraktionen können Sie jedoch bei Bedarf auf c, c ++ zugreifen. Stellen Sie sich vor, Sie könnten das in Java haben. Diese Frage ist es nicht einmal wert zu fragen, ob Jython in Ordnung ist, denn dann ist es sowieso einfach.

Also habe ich mit den folgenden Methoden gespielt und sie von leicht bis schwer aufgelistet:

Java nach Jython

Vorteile: Trivial einfach. Haben tatsächliche Verweise auf Java-Objekte

Nachteile: Kein CPython, extrem langsam!

Jython aus Java ist so einfach, und wenn das wirklich genug ist, dann großartig. Es ist jedoch sehr langsam und kein Python! Ist das Leben ohne Python lebenswert? Ich glaube nicht! Sie können leicht Python-Code haben, der Ihre Mitgliedsfunktionen für Ihre Java-Objekte implementiert.

Java nach Jython nach CPython über Pyro

Pyro ist das Remote-Objektmodul für Python. Sie haben ein Objekt auf einem Cpython-Interpreter, und Sie können ihm Objekte senden, die über die Serialisierung übertragen werden, und es können auch Objekte über diese Methode zurückgegeben werden. Beachten Sie, dass Sie diese Änderungen in Java nicht sehen, wenn Sie ein serialisiertes Python-Objekt von jython senden und dann einige Funktionen aufrufen, die die Daten in seinen Mitgliedern ändern. Sie müssen nur daran denken, die gewünschten Daten von pyro zurückzusenden. Dies ist meiner Meinung nach der einfachste Weg, um zu cpython zu gelangen! Sie brauchen kein jni oder jna oder swig oder ... Sie müssen kein c oder c ++ kennen. kool huh?

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

Nachteile: Die Mitgliedsdaten von Java-Objekten können nicht direkt in Python geändert werden. Ist etwas indirekt (Jython ist Middle Man).

Java zu C / C ++ über JNI / JNA / SWIG zu Python über Embedded Interpreter (möglicherweise mit BOOST Libraries?)

OMG diese Methode ist nichts für schwache Nerven. Und ich kann Ihnen sagen, dass ich sehr lange gebraucht habe, um dies mit einer anständigen Methode zu erreichen. Der Hauptgrund, warum Sie dies tun möchten, ist, dass Sie Cpython-Code ausführen können, der Ihr Java-Objekt vollständig beherrscht. Es gibt wichtige Dinge zu beachten, bevor Sie sich entscheiden, Java (das wie ein Schimpanse ist) mit Python (das wie ein Pferd ist) zu braten. Erstens, wenn Sie den Interpreter zum Absturz bringen, der für Ihr Programm ausfällt! Und lass mich nicht mit Parallelitätsproblemen anfangen! Darüber hinaus gibt es viel Kessel, ich glaube, ich habe die beste Konfiguration gefunden, um diesen Kessel zu minimieren, aber es ist immer noch viel! So gehen Sie vor: Betrachten Sie, dass C ++ Ihr Mittelsmann ist, Ihre Objekte sind tatsächlich C ++ - Objekte! Gut, dass du das jetzt weißt. Schreiben Sie einfach Ihr Objekt, als ob Ihr Programm wie in cpp nicht Java, mit den Daten, auf die Sie aus beiden Welten zugreifen möchten. Dann können Sie den Wrapper-Generator swig (http://www.swig.org/Doc1.3/Java.html ), um dies für Java zugänglich zu machen und eine DLL zu kompilieren, die Sie in Java als System.load (DLL-Name hier) bezeichnen. Lassen Sie dies zuerst funktionieren und fahren Sie dann mit dem schwierigen Teil fort! Um zu Python zu gelangen, müssen Sie einen Interpreter einbetten. Zuerst schlage ich vor, ein paar Hallo-Interpreter-Programme oder dieses Tutorial zu machen. Einbetten von Python in C / C. . Sobald Sie diese Arbeit haben, ist es Zeit, das Pferd und den Affen zum Tanzen zu bringen! Sie können Ihr C ++ - Objekt über [boost] [3] an Python senden. Ich weiß, ich habe dir den Fisch nicht gegeben, sondern dir nur gesagt, wo du den Fisch finden kannst. Einige Hinweise, die beim Kompilieren zu beachten sind.

Wenn Sie Boost kompilieren, müssen Sie eine gemeinsam genutzte Bibliothek kompilieren. Und Sie müssen die Inhalte von jdk, dh jawt.lib, jvm.lib, einbinden und mit ihnen verknüpfen (Sie benötigen beim Starten der Anwendung auch den Client jvm.dll in Ihrem Pfad) sowie die python27.lib oder was auch immer und die boost_python-vc100-mt-1_55.lib. Schließen Sie dann Python / include, jdk / include, boost ein und verwenden Sie nur gemeinsam genutzte Bibliotheken (DLLs), da Boost sonst einen Tränenfluss hat. Und ja voll auf ich weiß. Es gibt so viele Möglichkeiten, wie dies sauer werden kann. Stellen Sie also sicher, dass Sie alles Block für Block erledigen. Dann setzen Sie sie zusammen.


2
Hier eine Bibliothek, mit der Sie Ihre Python-Skripte einmal schreiben und entscheiden können, welche Integrationsmethode (Jython, CPython über Jep und Py4j) zur Laufzeit verwendet werden soll: github.com/subes/invesdwin-context-python Da jede Methode ihre eigenen Vor- und Nachteile hat
Subes

@subes das Projekt sieht toll aus Ich habe das vor einiger Zeit geschrieben. Ich ermutige Sie, eine Antwort zu schreiben, die ich positiv bewerten würde. Ich mag die Top-Antwort nicht, haha, weil ich nicht denke, dass sie außerhalb einer Google-Suche viele nützliche Informationen liefert.
Snickers3192

Ich habe eine separate Antwort erstellt
Subes

3
riecht diese Antwort nach "das sollte die akzeptierte Antwort sein" oder bin es nur ich? ;-)
Mauricio Gracia Gutierrez

18

Es ist nicht klug, Python-Code in Java zu haben. Wickeln Sie Ihren Python-Code mit einer Flasche oder einem anderen Webframework ein, um ihn als Microservice zu verwenden. Machen Sie Ihr Java-Programm in der Lage, diesen Microservice aufzurufen (z. B. über REST).

Glauben Sie mir, das ist sehr einfach und erspart Ihnen jede Menge Probleme. Und die Codes sind lose gekoppelt, so dass sie skalierbar sind.

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


+1, aber was ist mit dem zusätzlichen Leistungs- und Kommunikationsaufwand beim Erstellen und Parsen von Hin- und Her-Nachrichten an beiden Enden?
stx

Ja, dies muss eine API-Schnittstelle mit minimaler Eingabe / Ausgabe definieren. Es ist nicht klug, viele Daten zwischen Client / Server im Netzwerk zu übertragen. Wenn Sie eine solche Schnittstelle nicht definieren können, ist dieser Entwurfsansatz nicht geeignet.
Peiming Hu

10

In einigen Antworten wird erwähnt, dass Sie JNI oder JNA verwenden können, um auf cpython zuzugreifen. Ich würde jedoch nicht empfehlen, von vorne zu beginnen, da es bereits Open Source-Bibliotheken für den Zugriff auf cpython über Java gibt. Beispielsweise:


8

Hier eine Bibliothek, mit der Sie Ihre Python-Skripte einmal schreiben und entscheiden können, welche Integrationsmethode (Jython, CPython / PyPy über Jep und Py4j) zur Laufzeit verwendet werden soll:

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

Da jede Methode ihre eigenen Vor- und Nachteile hat, wie im Link erläutert.


Dieses Projekt hat keine Veröffentlichung.
Christian Schlichtherle

@ChristianSchlichtherle invesdwin-context-python Version 1.0.0 ist nicht verfügbar. danke an dieses kleine Juwel: github.com/loewenfels/dep-graph-releaser
subes

6

Es kommt darauf an, was du mit Python-Funktionen meinst. Wenn sie in cpython geschrieben wurden, können Sie sie nicht direkt aufrufen. Sie müssen JNI verwenden . Wenn sie jedoch in Jython geschrieben wurden, können Sie sie einfach aus Java aufrufen, da jython letztendlich Java-Bytecode generiert.

Wenn ich jetzt sage, dass es in cpython oder jython geschrieben ist, macht es wenig Sinn, da python python ist und der meiste Code auf beiden Implementierungen ausgeführt wird, es sei denn, Sie verwenden bestimmte Bibliotheken, die auf cpython oder java basieren.

Hier erfahren Sie, wie Sie den Python-Interpreter in Java verwenden.


5

Abhängig von Ihren Anforderungen können Optionen wie XML-RPC hilfreich sein, mit denen Funktionen praktisch in jeder Sprache, die das Protokoll unterstützt, remote aufgerufen werden können.


4

Sie können jede Sprache aus Java über Java Native Interface aufrufen


6
Jede Sprache, die selbst von c aufgerufen werden kann. Nun gut, Python kann, aber Jython ist dort wirklich eine viel einfachere Lösung (oder mit dem PyInterpreter in j6 +). Es ist nicht so trivial, den Code zum Aufrufen von Python-Funktionen von c zu schreiben.
Voo

2

Jython hat einige Einschränkungen:

Es gibt eine Reihe von Unterschieden. Erstens können Jython-Programme keine in C geschriebenen CPython-Erweiterungsmodule verwenden. Diese Module haben normalerweise Dateien mit der Erweiterung .so, .pyd oder .dll. Wenn Sie ein solches Modul verwenden möchten, sollten Sie nach einem Äquivalent suchen, das in reinem Python oder Java geschrieben ist. Obwohl es technisch machbar ist, solche Erweiterungen zu unterstützen - IronPython tut dies -, gibt es in Jython keine Pläne, dies zu tun.

Verteilen meiner Python-Skripte als JAR-Dateien mit Jython?

Sie können einfach Python-Skripte (oder Bash- oder Perl-Skripte) von Java mit Runtime oder ProcessBuilder aufrufen und die Ausgabe an Java zurückgeben:

Ausführen eines Bash-Shell-Skripts in Java

Ausführen der Befehlszeile in Java

java runtime.getruntime () erhält die Ausgabe von der Ausführung eines Befehlszeilenprogramms


0

Dies gibt einen ziemlich guten Überblick über die aktuellen Optionen. Einige davon sind in anderen Antworten genannt. Jython kann erst verwendet werden, wenn sie sich für die Implementierung von Python 3.x entscheiden. Viele der anderen Projekte kommen von der Python-Seite und möchten auf Java zugreifen. Es gibt jedoch noch einige Optionen, um etwas zu benennen, das noch nicht benannt wurde: gRPC


0

GraalVM ist eine gute Wahl. Ich habe Java + Javascript-Kombination mit GraalVM für das Microservice-Design (Java mit Javascript-Reflexion) durchgeführt. Sie haben kürzlich Unterstützung für Python hinzugefügt. Ich würde es versuchen, insbesondere, wie groß die Community im Laufe der Jahre geworden ist.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.