Wywołanie Pythona w Javie?


Odpowiedzi:


101

Jython: Python dla platformy Java - http://www.jython.org/index.html

Możesz łatwo wywoływać funkcje Pythona z kodu Java za pomocą Jythona. To jest tak długo, jak sam kod Pythona działa pod jythonem, tj. Nie używa niektórych rozszerzeń c, które nie są obsługiwane.

Jeśli to działa, z pewnością jest to najprostsze rozwiązanie, jakie możesz uzyskać. W przeciwnym razie możesz skorzystać org.python.util.PythonInterpreterz nowej obsługi interpretera Java6.

Prosty przykład z góry mojej głowy - ale mam nadzieję, że powinien zadziałać: (brak sprawdzania błędów dla zwięzłości)

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

Zainstalowałem JYthon lub zakładam, że tak, i nadal próbuję uruchomić kod, który nakreśliłeś, ale został on wyróżniony jako błąd. Czy instalacja Jythona musi przejść do określonego folderu, czy to w folderze python, czy java?
Shahab

2
Nie ma żadnego błędu, po prostu mam trudności z integracją Jythona z Netbeans
Shahab,

Jeśli nie ma błędu, to zadziała, więc oczywiście tak nie jest;) „Błąd” nie oznacza błędu w czasie wykonywania, może to być również błąd kompilacji.
Voo

Moja wina, to było kiepskie użycie tego słowa. Próbowałem dodać jython.jar do mojego projektu i netbeans. Rozgryzłem to jednak
Shahab

1
Koniec życia Pythona 2 to 1.1.2020, a Jython obsługuje tylko Python 2.7. więc żaden Jython nie jest w zasadzie martwy. Najlepszą (najprostszą) opcją jest Jep lib
garyee

63

Hej, myślałem, że podam swoją odpowiedź, mimo że jest późno. Myślę, że jest kilka ważnych rzeczy, które należy najpierw rozważyć, a mianowicie, jak silne chcesz mieć połączenie między Javą a Pythonem.

Po pierwsze, czy chcesz tylko wywoływać funkcje, czy faktycznie chcesz, aby kod Pythona zmieniał dane w obiektach Java? To jest bardzo ważne. Jeśli chcesz tylko wywołać jakiś kod Pythona z argumentami lub bez, to nie jest to zbyt trudne. Jeśli twoje argumenty są prymitywne, będzie to jeszcze łatwiejsze. Jeśli jednak chcesz mieć funkcje składowe klasy java implementujące w Pythonie, które zmieniają dane obiektu java, to nie jest to takie łatwe ani proste.

Po drugie, czy mówimy o cpythonie, czy też zrobi to jython? Powiedziałbym, że cpython jest tam, gdzie jest! Opowiadałbym się za tym, dlaczego Python jest taki kool! Mając tak wysokie abstrakcje, jednak w razie potrzeby dostęp do c, c ++. Wyobraź sobie, że możesz to mieć w Javie. To pytanie nie jest nawet warte pytania, czy jython jest w porządku, ponieważ i tak jest to łatwe.

Więc bawiłem się następującymi metodami i wymieniłem je od łatwych do trudnych:

Java na Jython

Zalety: banalnie proste. Mają rzeczywiste odniesienia do obiektów Java

Wady: brak CPythona, bardzo wolno!

Jython z javy jest tak łatwy, a jeśli to naprawdę wystarczy, to świetnie. Jednak jest bardzo powolny i nie ma cpythonu! Czy warto żyć bez cpythona, nie sądzę! Możesz łatwo mieć kod Pythona implementujący funkcje składowe dla obiektów Java.

Java na Jython na CPython przez Pyro

Pyro to zdalny moduł obiektowy dla Pythona. Masz jakiś obiekt na interpretatorze cpython i możesz wysłać mu obiekty, które są przesyłane przez serializację, a także może zwracać obiekty za pomocą tej metody. Zwróć uwagę, że jeśli wyślesz zserializowany obiekt Pythona z jythona, a następnie wywołasz funkcje, które zmieniają dane w jego elementach członkowskich, nie zobaczysz tych zmian w java. Musisz tylko pamiętać o odesłaniu żądanych danych z pyro. Myślę, że to najłatwiejszy sposób, aby dostać się do cpython! Nie potrzebujesz żadnego jni, jna, swig lub ... Nie musisz znać żadnego c ani c ++. kool co?

Zalety: Dostęp do cpython, nie tak trudny, jak następujące metody

Wady: nie można zmienić danych składowych obiektów Java bezpośrednio z Pythona. Jest nieco pośredni (jython jest pośrednikiem).

Java na C / C ++ przez JNI / JNA / SWIG do Pythona przez wbudowany interpreter (może przy użyciu bibliotek BOOST?)

OMG, ta metoda nie jest dla osób o słabym sercu. I mogę powiedzieć, że zajęło mi to bardzo dużo czasu, zanim udało mi się to osiągnąć przyzwoitą metodą. Głównym powodem, dla którego chciałbyś to zrobić, jest to, że możesz uruchomić kod cpython, który będzie miał pełną kontrolę nad obiektem Java. Przed podjęciem decyzji o spróbowaniu chleba java (który jest jak szympans) z pytonem (który jest jak koń), należy wziąć pod uwagę ważne kwestie. Po pierwsze, jeśli zawiesisz interpreter, który jest wyłączony dla twojego programu! I nie zaczynaj od kwestii współbieżności! Ponadto jest dużo kotła, wierzę, że znalazłem najlepszą konfigurację, aby zminimalizować ten kocioł, ale nadal jest! Jak więc się do tego zabrać: Weź pod uwagę, że C ++ jest twoim pośrednikiem, twoje obiekty to w rzeczywistości obiekty c ++! Dobrze, że już to wiesz. Po prostu napisz swój obiekt tak, jakby twój program był jak w cpp, a nie java, z danymi, do których chcesz uzyskać dostęp z obu światów. Następnie możesz użyć generatora opakowań o nazwie swig (http://www.swig.org/Doc1.3/Java.html ), aby udostępnić to java i skompilować bibliotekę dll, którą wywołujesz System.load (tutaj nazwa dll) w java. Najpierw zajmij się tym, a potem przejdź do najtrudniejszej części! Aby dostać się do Pythona, musisz osadzić interpreter. Po pierwsze proponuję robi kilka programów tłumacza hello czy ten samouczek Osadzanie Pythona w C / C . Kiedy już to zrobisz, pora zmusić konia i małpkę do tańca! Możesz wysłać obiekt C ++ do Pythona przez [boost] [3]. Wiem, że nie dałem ci ryby, powiedziałem tylko, gdzie ją znaleźć. Kilka wskazówek, na które należy zwrócić uwagę podczas kompilacji.

Podczas kompilacji przyspieszenia musisz skompilować bibliotekę współdzieloną. I musisz dołączyć i linkować do rzeczy, których potrzebujesz z jdk, tj. Jawt.lib, jvm.lib (będziesz również potrzebować klienta jvm.dll w swojej ścieżce podczas uruchamiania aplikacji), a także python27.lib lub cokolwiek i boost_python-vc100-mt-1_55.lib. Następnie dołącz Python / include, jdk / include, boost i używaj tylko bibliotek współdzielonych (dll), w przeciwnym razie boost ma kłopoty. I tak, w pełni wiem. Jest tak wiele sposobów, w jakie może się to zepsuć. Więc upewnij się, że wykonujesz każdą rzecz blok po bloku. Następnie złóż je razem.


2
Tutaj biblioteka, która pozwala raz napisać skrypty Pythona i zdecydować, której metody integracji (Jython, CPython przez Jep i Py4j) użyć w czasie wykonywania: github.com/subes/invesdwin-context-python Ponieważ każda metoda ma swoje zalety / wady
subes

@subes, ten projekt wygląda niesamowicie Napisałem to jakiś czas temu. Zachęcam do napisania odpowiedzi, którą zagłosowałbym za. Nie podoba mi się haha ​​najlepsza odpowiedź, ponieważ nie sądzę, aby zawierała wiele przydatnych informacji poza wyszukiwarką Google.
Snickers3192

Stworzyłem osobną odpowiedź
subes

3
czy ta odpowiedź pachnie "to powinna być akceptowana odpowiedź", czy to tylko ja? ;-)
Mauricio Gracia Gutierrez

18

Nie jest mądrze mieć kod Pythona w java. Zawiń swój kod w języku Python za pomocą platformy flask lub innej platformy internetowej, aby uczynić go mikrousługą. Spraw, aby Twój program java mógł wywoływać tę mikrousługę (np. Przez REST).

Uwierz mi, to jest o wiele proste i pozwoli Ci zaoszczędzić mnóstwo problemów. Kody są luźno powiązane, więc są skalowalne.

Zaktualizowano 24 marca 2020 r .: Zgodnie z komentarzem @ stx powyższe podejście nie nadaje się do masowego przesyłania danych między klientem a serwerem. Oto inne podejście, które poleciłem: Łączenie Pythona i Javy z Rustem (C / C ++ również ok). https://medium.com/@shmulikamar/https-medium-com-shmulikamar-connecting-python-and-java-with-rust-11c256a1dfb0


+1, ale co z dodatkową wydajnością i narzutem komunikacyjnym związanym z tworzeniem i analizowaniem wiadomości w obie strony na obu końcach?
stx

tak, to musi zdefiniować interfejs API z minimalnym wymaganym wejściem / wyjściem. Przesyłanie dużej ilości danych między klientem a serwerem w sieci nie jest rozsądne. Jeśli nie możesz zdefiniować takiego interfejsu, to podejście projektowe nie pasuje.
Peiming Hu

10

Kilka odpowiedzi wspomina, że ​​możesz użyć JNI lub JNA, aby uzyskać dostęp do cpython, ale nie polecałbym zaczynać od zera, ponieważ istnieją już biblioteki open source umożliwiające dostęp do cpython z javy. Na przykład:


8

Tutaj biblioteka, która pozwala ci raz napisać skrypty Pythona i zdecydować, której metody integracji (Jython, CPython / PyPy przez Jep i Py4j) użyć w czasie wykonywania:

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

Ponieważ każda metoda ma swoje zalety / wady, jak wyjaśniono w linku.


Ten projekt nie ma żadnego wydania.
Christian Schlichtherle

@ChristianSchlichtherle invesdwin-context-python wersja 1.0.0 nie jest dostępna; dzięki temu małemu klejnotowi: github.com/loewenfels/dep-graph-releaser
subes

6

To zależy od tego, co masz na myśli przez funkcje Pythona? jeśli zostały napisane w cpythonie , nie możesz ich bezpośrednio wywołać, będziesz musiał użyć JNI , ale jeśli zostały napisane w Jythonie możesz je łatwo wywołać z javy, ponieważ jython ostatecznie generuje kod bajtowy java.

Teraz, kiedy mówię napisane w cpythonie lub jythonie, nie ma to większego sensu, ponieważ python to python i większość kodu będzie działać na obu implementacjach, chyba że używasz określonych bibliotek, które opierają się na cpythonie lub javie.

zobacz tutaj, jak używać interpretera Pythona w Javie.


5

W zależności od wymagań przydatne mogą być opcje takie jak XML-RPC , które można wykorzystać do zdalnego wywoływania funkcji praktycznie w dowolnym języku obsługującym protokół.


5

GraalVM to dobry wybór. Zrobiłem połączenie Java + Javascript z GraalVM do projektowania mikrousług (Java z odzwierciedleniem Javascript). Niedawno dodali obsługę Pythona, spróbuję, szczególnie biorąc pod uwagę, jak duża stała się jego społeczność na przestrzeni lat.


4

Możesz wywołać dowolny język z javy przy użyciu natywnego interfejsu Java


6
Każdy język, który sam można nazwać z c to znaczy. No dobrze, Python może, ale Jython jest tam naprawdę znacznie prostszym rozwiązaniem (lub używając PyInterpreter w j6 +). Nie jest takie trywialne napisanie kodu wywołującego funkcje Pythona z c.
Voo

2

Jython ma pewne ograniczenia:

Istnieje wiele różnic. Po pierwsze, programy w języku Jython nie mogą używać modułów rozszerzających CPython napisanych w języku C. Moduły te zwykle mają pliki z rozszerzeniami .so, .pyd lub .dll. Jeśli chcesz skorzystać z takiego modułu, powinieneś poszukać odpowiednika napisanego w czystym Pythonie lub Javie. Chociaż obsługa takich rozszerzeń jest technicznie wykonalna - IronPython to robi - nie ma takich planów w Jythonie.

Rozpowszechnianie moich skryptów w języku Python jako plików JAR w języku Jython?

możesz po prostu wywołać skrypty Pythona (lub skrypty bash lub Perl) z języka Java za pomocą środowiska uruchomieniowego lub ProcessBuilder i przekazać dane wyjściowe z powrotem do języka Java:

Uruchamianie skryptu powłoki bash w java

Uruchamianie wiersza poleceń w Javie

java runtime.getruntime () pobiera dane wyjściowe z wykonania programu wiersza poleceń


0

To daje całkiem dobry przegląd ciągu bieżącej opcji. Niektóre z nich są wymienione w innych odpowiedziach. Jython nie nadaje się do użytku, dopóki nie zdecydują się na wdrożenie Pythona 3.x, a wiele innych projektów pochodzi ze strony Pythona i chce mieć dostęp do javy. Ale jest jeszcze kilka opcji, aby nazwać coś, co nie zostało jeszcze nazwane: gRPC

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.