以最有效的方式从 Java 重复调用 python

Repeatedly calling python from Java in the most efficient way

我有几个 python 脚本(例如 a.pyb.py)在顶部共享相同的开销,例如:

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

然后我有一个 java 脚本,用户运行时可以分别调用这几个 python 脚本:

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

由于 java 运行时和每次 python 调用期间的 python 导入开销,我遭受了重复的开销。我想知道是否有一种方法在第一次 python 调用期间只涉及一次开销(可能通过传递一些 python handler/state ?)我对第三方工具开放(例如Jython)也是如此。

您可以启动 Python 脚本一次,然后通过某种 IPC(inter-process 通信)与它通信重复的任务。想到的一些方法:

  • 通过 Python 进程(Java 进程作为客户端)托管的 HTTP API 访问
  • 如果使用 OS X/Linux 使用 signals
  • 像通过文件传递指令一样简单的东西——虽然你可能需要实现 file-locking(所以如果作者还没有完成,reader 不会读取不完整的文件)

但是,实施其中任何一个确实感觉有点像 premature-optimization。为什么不首先实施最简单的方法(如您的示例所示),然后分析您的 CPU 用法。很有可能,您当前的方法不会像您所怀疑的那样对您的 CPU 使用造成太大影响。

与其单独启动每个程序并 运行 完成,不如创建一个 "launcher" 从标准输入读取并与该启动器交互的程序 - 这应该是一个程序,直到它告诉;它的全部目的是启动其他功能。

然后将其视为资源并使用它来调用各个函数和 return 结果(而不是 Java 的 Process)。

相同的策略可用于具有共享依赖项的许多不同类型的外部程序 - 启动器可以加载公共依赖项/它自己的运行时一次,并更快地调用这些依赖项中的函数。

不确定这是否会加速您的程序,但一种选择是使用 Jython 启动一次 Python 解释器,然后 re-use 它用于多个脚本。您只需要添加对 Jython JAR 的依赖(在 http://www.jython.org/downloads.html 下载它或使用 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");
    }
}

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