7 Stimmen

Aufrufen von Python-Modulen aus Java

Ich habe eine Python-Schnittstelle eines Graphen-Bibliothek in C geschrieben - igraph (der Name der Bibliothek). Ich muss die Python-Module, die zu dieser Graphenbibliothek gehören, von Java-Code aus aufrufen. Der Kern der Bibliothek ist in C. Dieser Kern wurde in Python importiert und die Schnittstellen zu den im Kern eingebetteten Funktionen sind in Python verfügbar. Der restliche Code meines Projekts ist in Java und daher möchte ich die Graphenfunktionen auch in Java aufrufen. Ich habe Jython ausprobiert, um festzustellen, dass es in meinem Fall nicht funktioniert, da der Kerncode in C ist und Jython nichts unterstützt, was als C-DLL in den Python-Code importiert wird. Ich nehme an, dass es etwas geben muss, mit dem man C-Code von Java aus aufrufen kann, aber ich bin nicht gut in C, daher habe ich es nicht versucht. Mein letzter Ausweg scheint zu sein, den Python-Interpreter von der Kommandozeile aus mit Java auszuführen. Aber das ist schmutzig und schamlos. Um die Ergebnisse des Python-Codes zu verarbeiten, muss ich die Ergebnisse in eine Datei schreiben und in Java zurücklesen. Auch das ist ein schmutziger Weg. Gibt es etwas, das mir jemand vorschlagen kann? Vielen Dank an alle, die sich Zeit nehmen.


Vielen Dank, Igal, für die Antwort. Ich habe es mir angeschaut. Auf den ersten Blick sieht es so aus, als würde es einfach das Python-Skript aufrufen.

Jep jep = new Jep(false, SCRIPT_PATH, cl);
jep.set("query", query);
jep.runScript(SCRIPT_PATH + file);
jep.close();

Ist es nicht sehr ähnlich zu dem, was wir tun würden, wenn der Python-Interpreter von der Kommandozeile durch einen Java-Code aufgerufen.

Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("python test.py");

Die Frage ist, wie ich die vom Python-Skript generierten Ergebnisse verwenden kann. Der naive Weg ist, sie in eine Datei zu schreiben und sie in Java zurückzulesen. Ich bin auf der Suche nach einem intelligenteren Ansatz und danke für jeden Vorschlag.

4voto

Igal Serban Punkte 10330

Ich habe es nie ausprobiert. Aber ich habe kürzlich stolperte in einem Projekt namens Jepp die für Sie von Interesse sein könnten.

Jepp bettet CPython in Java ein. Es ist sicher in einer Umgebung mit vielen Threads zu verwenden, es ist ziemlich schnell und seine Stabilität ist ein Hauptmerkmal und Ziel.

4voto

Tamás Punkte 45697

Wenn Sie C-Funktionen von Java aus aufrufen wollen, JNA (Java Native Access) ist wahrscheinlich der richtige Weg. Mit JNA können Sie Funktionen in nativen Bibliotheken aufrufen, ohne den C-Glue-Code schreiben zu müssen (wie es bei der Verwendung von JNI der Fall wäre), und es erfolgt eine automatische Zuordnung zwischen primitiven Datentypen in Java und C. Ein einfaches Beispiel könnte wie folgt aussehen:

import com.sun.jna.Native;
import com.sun.jna.Library;

public class PrintfWrapper {
    public interface CLibrary extends Library {
        CLibrary INSTANCE = (CLibrary)Native.loadLibrary("c", CLibrary.class);
        void printf(String formatString, Object... args);
    }

    public static void main(String[] args) {
        CLibrary.INSTANCE.printf("Hello, world\n");
    }
}

Allerdings werden die Dinge mit igraph kompliziert, da igraph viele Datenstrukturen verwendet, die nicht direkt auf ihre Java-Gegenstücke abgebildet werden können. Es gibt ein Projekt namens JNAerator das in der Lage sein sollte, den JNA-Quellcode aus den Header-Dateien von igraph zu generieren, aber ich habe es nie ausprobiert, und es ist wahrscheinlich, dass die Ergebnisse immer noch manuell angepasst werden müssen.

Beachten Sie auch, dass ein Java-Schnittstelle für igraph wird langsam, aber stetig weiterentwickelt und könnte in einigen Monaten nützlich werden.

2voto

Mike Johnson Punkte 695

Sie können jep.getValue() verwenden, um einen Wert aus dem globalen Wörterbuch des Skripts abzurufen.

Es gibt einige Einschränkungen in Bezug auf die Geltungsbereiche in Python, so dass es für die meisten Leute klarer ist, eine Java-Klasse an Python zu übergeben und den Rückgabewert in dieser Instanz in Python zu setzen. Nach Beendigung des Skripts steht dem Java-Code dann das Ergebnis zur Verfügung.

Zum Beispiel:

\==> Java

class ReturnValueClass {
   public int scriptResult;
};
ReturnValueClass value = new ReturnValueClass();
jep.set("retval", value);

\==> Python

# do something
pass
# write the return value
retval.scriptResult = some_python_value

\==> Java

System.out.println(value.scriptResult);

Ich hoffe, das hilft,

Mike (ich schrieb Jep)

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