¿Llamar a Python en Java?

117

Me pregunto si es posible llamar a funciones de Python desde el código java usando jython, o ¿es solo para llamar al código Java desde Python?

Shahab
fuente
3
Por favor, eche un vistazo a una pregunta similar y lea la respuesta. bytes.com/topic/python/answers/…
AlexR

Respuestas:

101

Jython: Python para la plataforma Java - http://www.jython.org/index.html

Puede llamar fácilmente a funciones de Python desde código Java con Jython. Eso es siempre y cuando su código Python se ejecute bajo jython, es decir, no use algunas extensiones C que no son compatibles.

Si eso funciona para usted, ciertamente es la solución más simple que puede obtener. De lo contrario, puede utilizar org.python.util.PythonInterpreterdesde el nuevo soporte de intérprete de Java6.

Un ejemplo simple desde la parte superior de mi cabeza, pero debería funcionar, espero: (no se realizó una verificación de errores por brevedad)

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);
Voo
fuente
Instalé JYthon, o supongo que lo hice, y sigo intentando ejecutar el código que describiste, pero se destacó como un error. ¿La instalación de Jython debe ir a una carpeta específica, ya sea en las carpetas de python o java?
Shahab
2
No hay ningún error, solo estoy teniendo dificultades para integrar Jython en Netbeans
Shahab
Si no hay ningún error, funcionaría, así que obviamente ese no es el caso;) "Error" no significa un error de tiempo de ejecución, también podría ser un error de compilación.
Voo
Mi mal, fue un mal uso de la palabra. Estaba tratando de agregar jython.jar a mi proyecto y netbeans. Sin embargo, lo descubrí
Shahab
1
El final de la vida útil de Python 2 es 1.1.2020 y Jython solo es compatible con Python 2.7. por lo que ningún Jython está básicamente muerto. La mejor opción (la más simple) es Jep lib
garyee
63

Oye, pensé en ingresar mi respuesta a esto, aunque es tarde. Creo que hay algunas cosas importantes a considerar primero con qué tan fuerte desea tener el enlace entre Java y Python.

En primer lugar, ¿solo desea llamar a funciones o realmente desea que el código Python cambie los datos en sus objetos java? Esto es muy importante. Si solo desea llamar a algún código Python con o sin argumentos, entonces eso no es muy difícil. Si sus argumentos son primitivos, lo hace aún más fácil. Sin embargo, si desea que la clase java implemente funciones miembro en python, que cambian los datos del objeto java, entonces esto no es tan fácil ni sencillo.

En segundo lugar, ¿estamos hablando de cpython o lo hará jython? ¡Yo diría que cpython es donde está! ¡Yo recomendaría que esta es la razón por la que Python es tan genial! Tener tan altas abstracciones sin embargo acceso a c, c ++ cuando sea necesario. Imagínese si pudiera tener eso en java. Esta pregunta ni siquiera vale la pena preguntar si jython está bien porque de todos modos es fácil.

Así que he jugado con los siguientes métodos y los he enumerado de fácil a difícil:

Java a Jython

Ventajas: Trivialmente fácil. Tener referencias reales a objetos java.

Desventajas: ¡ Sin CPython, extremadamente lento!

Jython de Java es muy fácil, y si esto es realmente suficiente, entonces genial. ¡Sin embargo, es muy lento y sin cpython! ¿Vale la pena vivir la vida sin cpython? ¡No lo creo! Puede hacer que el código Python implemente sus funciones miembro para sus objetos java.

Java a Jython a CPython a través de Pyro

Pyro es el módulo de objeto remoto para Python. Tiene algún objeto en un intérprete de cpython y puede enviarle objetos que se transfieren mediante serialización y también puede devolver objetos a través de este método. Tenga en cuenta que si envía un objeto python serializado desde jython y luego llama a algunas funciones que cambian los datos en sus miembros, entonces no verá esos cambios en java. Solo necesita recordar enviar de vuelta los datos que desea de Pyro. ¡Creo que esta es la forma más fácil de llegar a cpython! No necesitas ningún jni o jna o un trago o .... No necesitas saber ningún c, o c ++. kool ¿eh?

Ventajas: acceso a cpython, no tan difícil como los siguientes métodos

Desventajas: no se pueden cambiar los datos de los miembros de los objetos java directamente desde python. Es algo indirecto (jython es intermediario).

Java a C / C ++ a través de JNI / JNA / SWIG a Python a través del intérprete integrado (¿tal vez usando bibliotecas BOOST?)

Dios mío, este método no es para los débiles de corazón. Y puedo decirles que me ha llevado mucho tiempo lograr esto con un método decente. La razón principal por la que querría hacer esto es para poder ejecutar el código cpython, que es el control total sobre su objeto java. Hay cosas importantes a tener en cuenta antes de decidir probar y pan Java (que es como un chimpancé) con Python (que es como un caballo). En primer lugar, si bloquea el intérprete que se apaga para su programa. ¡Y no me hagas empezar con problemas de concurrencia! Además, hay una gran cantidad de caldera, creo que he encontrado la mejor configuración para minimizar esta caldera, ¡pero aún así es suficiente! Entonces, ¿cómo hacer esto? Considere que C ++ es su intermediario, ¡sus objetos son en realidad objetos de C ++! Es bueno que lo sepas ahora. Simplemente escriba su objeto como si su programa como en cpp no ​​java, con los datos a los que desea acceder desde ambos mundos. Entonces puedes usar el generador de envoltorios llamado swig (http://www.swig.org/Doc1.3/Java.html ) para hacer esto accesible para java y compile un dll al que llame System.load (nombre dll aquí) en java. ¡Haga que esto funcione primero, luego pase a la parte difícil! Para llegar a Python, necesita incrustar un intérprete. En primer lugar Sugiero hacer algunos programas de interpretación hola o este tutorial Empotrado de Python en C / C . Una vez que lo tengas funcionando, ¡es hora de hacer bailar al caballo y al mono! Puede enviar su objeto c ++ a Python a través de [boost] [3]. Sé que no te he dado el pescado, simplemente te he dicho dónde encontrarlo. Algunos consejos a tener en cuenta al compilar.

Cuando compile boost, deberá compilar una biblioteca compartida. Y debe incluir y vincular a las cosas que necesita de jdk, es decir, jawt.lib, jvm.lib, (también necesitará el cliente jvm.dll en su ruta al iniciar la aplicación), así como el python27.lib o lo que sea y el boost_python-vc100-mt-1_55.lib. Luego incluya Python / include, jdk / include, boost y solo use bibliotecas compartidas (dlls); de lo contrario, boost tiene problemas. Y sí, lo sé. Hay muchas formas en las que esto puede estropearse. Así que asegúrese de hacer cada cosa bloque a bloque. Luego júntelos.

Snickers3192
fuente
2
Aquí una biblioteca que le permite escribir sus scripts de Python una vez y decidir qué método de integración (Jython, CPython a través de Jep y Py4j) usar en tiempo de ejecución: github.com/subes/invesdwin-context-python Dado que cada método tiene sus propios beneficios / inconvenientes
subes
@subes ese proyecto se ve increíble. Escribí esto hace un tiempo. Te animo a que escribas una respuesta. Yo la votaría. No me gusta la respuesta principal jaja porque no creo que proporcione mucha información útil fuera de una búsqueda en Google.
Snickers3192
Creé
3
¿Esta respuesta huele a "esta debería ser la respuesta aceptada" o soy solo yo? ;-)
Mauricio Gracia Gutierrez
18

No es inteligente tener código Python dentro de Java. Envuelva su código de Python con un matraz u otro marco web para convertirlo en un microservicio. Haga que su programa Java pueda llamar a este microservicio (por ejemplo, a través de REST).

Créame, esto es muy simple y le ahorrará toneladas de problemas. Y los códigos están débilmente acoplados para que sean escalables.

Actualizado el 24 de marzo de 2020: según el comentario de @ stx, el enfoque anterior no es adecuado para la transferencia masiva de datos entre el cliente y el servidor. Aquí hay otro enfoque que recomendé: Conectar Python y Java con Rust (C / C ++ también está bien). https://medium.com/@shmulikamar/https-medium-com-shmulikamar-connecting-python-and-java-with-rust-11c256a1dfb0

Peiming Hu
fuente
+1, pero ¿qué pasa con el rendimiento adicional y la sobrecarga de comunicación de crear y analizar mensajes de ida y vuelta en ambos extremos?
stx
sí, esto necesita definir una interfaz api con una entrada / salida mínima requerida. No es inteligente tener una gran cantidad de transferencia de datos entre cliente / servidor en la red. Si no puede definir una interfaz de este tipo, este enfoque de diseño no se adapta.
Peiming Hu
10

Varias de las respuestas mencionan que puede usar JNI o ​​JNA para acceder a cpython, pero no recomendaría comenzar desde cero porque ya existen bibliotecas de código abierto para acceder a cpython desde java. Por ejemplo:

bsteffen
fuente
8

Aquí una biblioteca que le permite escribir sus scripts de Python una vez y decidir qué método de integración (Jython, CPython / PyPy a través de Jep y Py4j) usar en tiempo de ejecución:

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

Dado que cada método tiene sus propios beneficios / inconvenientes, como se explica en el enlace.

subes
fuente
Este proyecto no tiene ningún lanzamiento.
Christian Schlichtherle
@ChristianSchlichtherle invesdwin-context-python versión 1.0.0 no está disponible; gracias a esta pequeña joya: github.com/loewenfels/dep-graph-releaser
subes
6

Depende de lo que quieras decir con funciones de Python. si se escribieron en cpython, no puede llamarlos directamente, tendrá que usar JNI , pero si se escribieron en Jython , puede llamarlos fácilmente desde java, ya que jython finalmente genera un código de bytes de java.

Ahora, cuando digo escrito en cpython o jython, no tiene mucho sentido porque python es python y la mayoría del código se ejecutará en ambas implementaciones a menos que esté utilizando bibliotecas específicas que se basan en cpython o java.

vea aquí cómo usar el intérprete de Python en Java.

Anurag Uniyal
fuente
5

Dependiendo de sus requisitos, las opciones como XML-RPC podrían ser útiles, que se pueden utilizar para llamar de forma remota a funciones prácticamente en cualquier idioma que admita el protocolo.

Timo
fuente
5

GraalVM es una buena opción. He hecho una combinación de Java + Javascript con GraalVM para el diseño de microservicios (Java con reflexión de Javascript). Recientemente agregaron soporte para Python, lo probaría especialmente con lo grande que se ha vuelto su comunidad a lo largo de los años.

Martillo Salvaje
fuente
4

Puede llamar a cualquier idioma desde Java utilizando la interfaz nativa de Java

nidhin
fuente
6
Es decir, cualquier idioma que se pueda llamar desde c. Bueno, de acuerdo, Python puede, pero Jython es una solución mucho más simple en realidad (o usando PyInterpreter en j6 +). No es tan trivial escribir el código para llamar funciones de Python desde c.
Voo
2

Jython tiene algunas limitaciones:

Hay varias diferencias. Primero, los programas Jython no pueden usar módulos de extensión CPython escritos en C. Estos módulos generalmente tienen archivos con la extensión .so, .pyd o .dll. Si desea utilizar un módulo de este tipo, debe buscar un equivalente escrito en Python o Java puro. Aunque es técnicamente factible admitir tales extensiones (IronPython lo hace), no hay planes para hacerlo en Jython.

¿Distribuir mis scripts de Python como archivos JAR con Jython?

simplemente puede llamar scripts de Python (o scripts bash o Perl) desde Java usando Runtime o ProcessBuilder y pasar la salida a Java:

Ejecutando un script de shell bash en java

Ejecución de la línea de comandos en Java

java runtime.getruntime () obteniendo resultados al ejecutar un programa de línea de comando

alex
fuente
0

Esto ofrece una descripción general bastante buena de las opciones actuales. Algunos de los cuales se nombran en otras respuestas. Jython no se puede utilizar hasta que deciden implementar Python 3.xy muchos de los otros proyectos vienen del lado de Python y quieren acceder a Java. Pero todavía hay algunas opciones, para nombrar algo que aún no ha sido nombrado: gRPC

garyee
fuente