【问题标题】:How to run python from java correctly?如何正确从java运行python?
【发布时间】:2018-08-14 09:07:29
【问题描述】:

我有下一个方法:

public void callPython() throws IOException {
        Runtime rt = Runtime.getRuntime();
        Process pr = rt.exec("python -c \"from test import read_and_show; read_and_show()\" src/main/python");

        BufferedReader bfr = new BufferedReader(new InputStreamReader(pr.getInputStream()));
        BufferedReader bfre = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
        String outputStr = "";
        while ((outputStr = bfr.readLine()) != null) {
            System.out.println(outputStr);
        }
        while ((outputStr = bfre.readLine()) != null) {
            System.out.println(outputStr);
        }
    }

在python文件下一个代码:

import os
from stat import *

def read_and_show():
    print('worked!')

当我在终端中调用它时一切正常(在我 cd 到这个目录之前):

MacBook-Pro-Nikita-2:python NG$ python -c "from test import read_and_show; read_and_show()"
worked!

当我在我的 java 代码中运行此代码时,他返回错误:

  File "<string>", line 1
    "from
        ^
SyntaxError: EOL while scanning string literal

我做错了什么?

P.S.:我需要运行 python 方法/类/文件来读取、解析和显示图形数据。但是对于java运行python单方法(def)时的这个需要

【问题讨论】:

  • 是python将错误打印回java,而不是java抛出异常,对吧?
  • 你说得对@phflack。但是,如果我在终端中运行相等的字符串,则一切正常
  • 如果将行更改为python -c \"print('test')\" 会发生什么?奇怪的是空间会是一个问题
  • @phflack 空结果)
  • 尝试让它在一个.bat文件中工作并从java中执行,它会少一些麻烦

标签: java python macos terminal


【解决方案1】:

当从 java 执行其他程序时,我发现在 java 中保持尽可能简单并执行批处理文件会更容易

Runtime.getRuntime().exec("chrome.exe www.google.com");

会变成

Runtime.getRuntime().exec("openChrome.bat");

和 openChrome.bat:

chrome.exe www.google.com

这使得无需重新编译即可更轻松地测试命令,但如果您需要将变量作为参数传递,则可能会变得复杂

要使用像echocd 这样的shell 内置函数,批处理文件的效果非常好(即echo test | program


主要的缺点是代码旁边会有一个浮动的 .bat 文件

如果打包成.jar,可能需要先copy the .bat file out of the .jar再执行

【讨论】:

    【解决方案2】:

    您缺少说明 python 解释器所在位置的 shebang 语句。它应该是第 1 行

    #!/usr/bin/python
    

    【讨论】:

    • 虽然文件中缺少它,但它如何改变从命令行与从 java 执行相同命令的行为?我认为它会在两种情况下都失败或在两种情况下都成功
    • 如果你输入“python”,然后从命令行启动 python,那么你已经手动找到了解释器。如果你从其他地方运行脚本,你需要告诉脚本解释器在哪里。
    • 是的,但看起来他们将所有内容都作为参数而不是用户输入传递
    【解决方案3】:

    Runtime.exec 已过时。很久以前就被ProcessBuilder class取代了:

    ProcessBuilder builder = new ProcessBuilder(
        "python", "-c", "from test import read_and_show; read_and_show()", "src/main/python");
    builder.redirectInput(ProcessBuilder.Redirect.INHERIT);
    Process pr = builder.start();
    

    注意from test import read_and_show; read_and_show() not 周围有双引号字符。这些引号是外壳使用的东西(例如bash)。 python 命令从未真正看到它们,也不应该看到它们。从 Java(或任何其他语言,实际上)执行子进程不会调用 shell;它直接执行命令。这意味着引号不会被任何 shell 解释,它们会作为参数的一部分传递给 python 程序。

    【讨论】:

      猜你喜欢
      • 2017-01-10
      • 2015-04-21
      • 2015-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多