簡體   English   中英

無法從java程序執行R腳本?

[英]not able to execute R script from java program?

我在String變量中有一個Rscript,我想從Java程序執行它並將一些變量傳遞給它。 如果我獨立執行該R腳本,它可以正常工作。 我通過使用Python程序將所有R腳本轉換為一行,如下所示:

import json

jsonstr = json.dumps({"script": """\
#!/usr/bin/Rscript

# read the data file
library('jsonlite')
library('rpart')

args <- as.list(Sys.getenv(c(
                        "path",
                        "client_users")))

if (args[["path"]]==""){
    args[["path"]] <- "."
}

# other stuff here
# other stuff here

"""})

print jsonstr

我使用打印出來的字符串並將其存儲在String變量中,然后我執行下面的代碼,它根本不起作用。 我將pathclient_users變量傳遞給上面的R腳本。

public static void main(String[] args) throws IOException, InterruptedException {

    // this is your script in a string
    // String script = "#!/bin/bash\n\necho \"Hello World\"\n\n readonly PARAM1=$param1\n echo $PARAM1\n\nreadonly PARAM2=$param2\n echo $PARAM2\n\n";
    String script = "above R Script here";

    List<String> commandList = new ArrayList<>();
    commandList.add("/bin/bash");

    ProcessBuilder builder = new ProcessBuilder(commandList);
    builder.environment().put("path", "/home/david");
    builder.environment().put("client_users", "1000");
    builder.redirectErrorStream(true);
    Process shell = builder.start();

    // Send your script to the input of the shell, something
    // like doing cat script.sh | bash in the terminal
    try(OutputStream commands = shell.getOutputStream()) {
        commands.write(script.getBytes());
    }

    // read the outcome
    try(BufferedReader reader = new BufferedReader(new InputStreamReader(shell.getInputStream()))) {
        String line;
        while((line = reader.readLine()) != null) {
            System.out.println(line);
        }
    }

    // check the exit code
    int exitCode = shell.waitFor();
    System.out.println("EXIT CODE: " + exitCode);
}

上面的代碼適用於bash shell腳本。 我需要為R腳本做些什么特別的事嗎? 我將對bash腳本和R腳本使用相同的代碼。

這是我得到的錯誤:

/bin/bash: line 7: -: No such file or directory /bin/bash: line 10: syntax error near unexpected token `'jsonlite'' /bin/bash: line 10: `library('jsonlite')' 

如果我刪除commandList.add("/bin/bash"); 並添加commandList.add("/bin/Rscript"); 然后我看到下面的錯誤:

Cannot run program "/bin/Rscript": error=2, No such file or directory

更新: -

我沒有使用上面的腳本,而是決定在r中使用簡單的打印地獄腳本來查看是否可以通過Java執行它。

// this will print hello
String script = "#!/usr/bin/env Rscript\nsayHello <- function(){\n   print('hello')\n}\n\nsayHello()\n";

當我用commandList.add("/bin/bash");執行此腳本時commandList.add("/bin/bash"); ,我收到此錯誤:

/bin/bash: line 2: syntax error near unexpected token `('
/bin/bash: line 2: `sayHello <- function(){'

但是如果我用這個commandList.add("/bin/sh"); ,我收到此錯誤:

/bin/sh: 2: Syntax error: "(" unexpected

您必須直接運行/usr/bin/Rscript 此外,此程序不讀取標准輸入中的腳本(您必須指定腳本的路徑作為Rscript的參數),因此您必須:

  • 創建臨時文件
  • 寫你的腳本
  • 使用Rscript執行腳本
  • 刪除你的臨時文件(作為一個很好的編程實踐)

例如,這是一個POC:

public static void main(String[] args) throws IOException, InterruptedException {

    // Your script
    String script = "#!/usr/bin/env Rscript\n" +
            "\n" +
            "sayHello <- function() {\n" +
            "    print('hello')\n" +
            "}\n" +
            "\n" +
            "sayHello()\n";

    // create a temp file and write your script to it
    File tempScript = File.createTempFile("test_r_scripts_", "");
    try(OutputStream output = new FileOutputStream(tempScript)) {
        output.write(script.getBytes());
    }

    // build the process object and start it
    List<String> commandList = new ArrayList<>();
    commandList.add("/usr/bin/Rscript");
    commandList.add(tempScript.getAbsolutePath());
    ProcessBuilder builder = new ProcessBuilder(commandList);
    builder.redirectErrorStream(true);
    Process shell = builder.start();

    // read the output and show it
    try(BufferedReader reader = new BufferedReader(
            new InputStreamReader(shell.getInputStream()))) {
        String line;
        while((line = reader.readLine()) != null) {
            System.out.println(line);
        }
    }

    // wait for the process to finish
    int exitCode = shell.waitFor();

    // delete your temp file
    tempScript.delete();

    // check the exit code (exit code = 0 usually means "executed ok")
    System.out.println("EXIT CODE: " + exitCode);
}

作為替代方案, 如果您的腳本有第一行“shebang” ,您可以執行以下更改:

  • 將其可執行屬性設置為“true”
  • 使用臨時文件的路徑作為commandList中的第一個元素(即刪除commandList.add("/usr/bin/Rscript");

要修改的代碼部分是:

...

// create a temp file and write your script to it
File tempScript = File.createTempFile("test_r_scripts_", "");
tempScript.setExecutable(true);
try(OutputStream output = new FileOutputStream(tempScript)) {
    output.write(script.getBytes());
}

// build the process object and start it
List<String> commandList = new ArrayList<>();
commandList.add(tempScript.getAbsolutePath());
ProcessBuilder builder = new ProcessBuilder(commandList);

...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM