【问题标题】:Interaction between Java App and Python AppJava App 和 Python App 之间的交互
【发布时间】:2010-12-31 08:44:37
【问题描述】:

我有一个 python 应用程序,从我的角度来看,我无法编辑它的黑匣子。 python 应用程序知道如何处理文本并返回处理后的文本。 我有另一个用 Java 编写的应用程序,它知道如何收集未处理的文本。

当前状态,python 应用每 x 分钟以批处理模式运行一次。

我想做python

处理部分流程:Java 应用程序收集文本并请求 python 应用程序处理并返回处理后的文本作为流程的一部分。

您认为最简单的解决方案是什么?

谢谢, 棒

【问题讨论】:

  • python程序如何接受输入?这没有多大意义,它是每 X 分钟从一个目录读取,还是从 STDIO 读取?你自己执行代码还是什么?

标签: java python interface interaction


【解决方案1】:

使用ProcessBuilder 执行您的Python 代码作为过滤器:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class PBTest {

    public static void main(String[] args) {
        ProcessBuilder pb = new ProcessBuilder("python", "-c", "print 42");
        pb.redirectErrorStream(true);
        try {
            Process p = pb.start();
            String s;
            BufferedReader stdout = new BufferedReader (
                new InputStreamReader(p.getInputStream()));
            while ((s = stdout.readLine()) != null) {
                System.out.println(s);
            }
            System.out.println("Exit value: " + p.waitFor());
            p.getInputStream().close();
            p.getOutputStream().close();
            p.getErrorStream().close();
         } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

【讨论】:

    【解决方案2】:

    一个选项是让 python 应用程序作为服务器工作,通过套接字 (TCP) 侦听请求。

    【讨论】:

      【解决方案3】:

      我对 Jython 之类的一无所知。我想这是最好的解决方案,如果您可以在每次 Java 应用程序需要转换文本时执行两个程序而无需执行新进程。无论如何,一个简单的概念证明是从 Java 应用程序执行一个单独的进程以使其工作。接下来,您可以使用所有这些工具来增强执行。

      从 Java 执行单独的进程

      String[] envprops = new String[] {"PROP1=VAL1", "PROP2=VAL2" };
      Process pythonProc = Runtime.getRuntime().exec(
         "the command to execute the python app", 
          envprops, 
          new File("/workingdirectory"));
      
      // get an outputstream to write into the standard input of python
      OutputStream toPython = pythonProc.getOutputStream();
      
      // get an inputstream to read from the standard output of python
      InputStream fromPython = pythonProc.getInputStream();
      
      // send something
      toPython.write(.....);
      // receive something
      fromPython.read(....);
      

      重要提示:字符不是字节

      很多人都低估了这一点。

      注意字符到字节的转换(记住 Writers/Readers 用于 chars,Input/OutputStreams 用于字节,编码是相互转换所必需的,您可以使用 OuputStreamWriter 将字符串转换为字节并发送,@ 987654323@ 将字节转换为字符并读取它们)。

      【讨论】:

      • 当然这意味着python应用程序必须从标准输入读取并写入标准输出。祝你好运!
      • 它不会只返回python进程的退出代码吗?如果不是,那么 inputStream 中的哪些内容会被视为可用?
      • 没有。从调用的(python)进程中,您有一个 STDIN 和一个 STDOUT(还有一个 STDERR :)。 Java 可以挂钩它们,写入一个并读取另一个。当您执行 printf("...") (对不起,我不了解 Python)时,您正在写入标准输出。当您在 Windows 命令行中执行“dir | more”或在 Linux 中执行“ls | nl”之类的操作时,您会将第一个程序的 STDOUT 重定向到第二个程序的 STDIN。如果你想要进程的返回码,你必须调用 pythonProc.waitFor()。这会返回一个 int。
      【解决方案4】:

      一种可能的解决方案是jpype。这允许您从 Python 启动 JVM 并在它们之间来回传递数据。

      另一种解决方案可能是将 Python 程序编写为过滤器(从标准输入读取数据并将结果写入标准输出),然后将其作为管道运行。但是我不知道 Java 对此的支持情况如何——根据 Sun 文档,他们的管道概念仅支持同一 JVM 上的线程之间的通信。

      【讨论】:

        【解决方案5】:

        将两者中的一个公开为某种服务,也许是 Web 服务。另一种选择是将 python 代码移植到 Jython

        【讨论】:

          【解决方案6】:

          查看Jython - 您可以直接从 Java 代码运行 Python 程序,并来回无缝交互。

          【讨论】:

          • 即使不更改 python 代码,您也应该能够使 Jython 工作。
          • 我想把 Python 当作一个黑色的封闭盒子。更像是一个服务器。 Python 如何很好地使用套接字?
          • @Rod:Jython 是运行在 JVM 上的 python,它仍然是一个“黑匣子”。只是Java可以在不使用套接字的情况下调用它。而且由于您使用的是 Java,因此这是最好的方法。
          • 我是否必须在我的 Java 应用程序中嵌入 Python 应用程序代码?还是可以作为中间技术使用?
          • 如果 Python 代码依赖于任何 C 扩展(例如 numpy),Jython 将无法工作。此外,并非所有 Python 功能都存在于 Jython 中,这会导致 NLTK 中出现诸如此 (bugs.jython.org/issue1398) 之类的错误。尝试在 Jython 上运行并没有什么坏处,但我个人会使用其中一种启动单独进程的解决方案。
          猜你喜欢
          • 2019-03-01
          • 2012-09-12
          • 1970-01-01
          • 2013-12-31
          • 2015-05-24
          • 1970-01-01
          • 2019-06-12
          • 2015-03-31
          相关资源
          最近更新 更多