Llamar repetidamente a python desde Java de la manera más eficiente.

Tengo varios scripts de Python (por ejemplo, a.py , b.py ) que comparten la misma sobrecarga en la parte superior, por ejemplo:

 import matplotlib.pylab as plt #and some Oracle database connection and reading. 

Luego tengo un script java que los usuarios Runtime llaman a estos varios scripts de Python por separado:

 Process p = Runtime.getRuntime().exec("python a.py"); p.waitFor(); ... p = Runtime.getRuntime().exec("python b.py"); p.waitFor(); 

Sufro por la repetición de sobrecarga debido a la sobrecarga de importación de Java en tiempo de ejecución y python durante cada llamada a python. Me pregunto si hay una forma que implique solo una sobrecarga de tiempo durante la primera llamada a Python (¿pasando por algún controlador / estado de Python, tal vez?) También estoy abierto a herramientas de terceros (por ejemplo, Jython).

En lugar de ejecutar cada progtwig por separado y ejecutarse hasta su finalización, cree un “iniciador” que se lea desde la entrada estándar e interactúe con ese iniciador; este debería ser un progtwig que no se cerrará hasta que se le indique; todo su propósito es lanzar otras funciones.

Luego, trátelo como un recurso y utilícelo para llamar a las funciones individuales y devolver los resultados (en lugar del Process de Java).

La misma estrategia se puede usar para muchos tipos diferentes de progtwigs externos que tienen dependencias compartidas: el iniciador puede cargar las dependencias comunes / su propio tiempo de ejecución una vez, y llamar más rápidamente a las funciones en esas dependencias.

Podría iniciar el script Python una vez y luego comunicar tareas repetidas con él a través de algún tipo de IPC (comunicación entre procesos). Algunas formas que vienen a la mente:

  • Acceso a través de una API HTTP alojada por el proceso Python (proceso Java como cliente)
  • Si usa OS X / Linux use señales
  • Algo tan simple como entregar instrucciones a través de un archivo, aunque probablemente necesite implementar el locking de archivos (por lo que el lector no lee un archivo incompleto si el escritor no ha terminado)

Sin embargo, la implementación de cualquiera de estos se siente un poco como una optimización prematura . ¿Por qué no implementar primero la forma más fácil (como en su ejemplo) y perfilar el uso de su CPU? Es probable que su enfoque actual no haga tanto daño en el uso de la CPU como podría sospechar.

No estoy seguro de si esto acelerará su progtwig, pero una opción sería usar Jython para iniciar un intérprete de Python una vez, y luego reutilizarlo para múltiples scripts. Solo necesita agregar una dependencia en el Jython JAR (descárguelo en http://www.jython.org/downloads.html o use Maven / Gradle / etc.)

 import org.python.util.PythonInterpreter; public class JythonTest { public static void main(String[] args) { PythonInterpreter pythonInterpreter = new PythonInterpreter(); pythonInterpreter.execfile("a.py"); pythonInterpreter.execfile("b.py"); } } 

Ref: http://tssblog.blogs.techtarget.com/2007/11/21/using-python-within-java/