2015-09-16 33 views
5

Ho un Rscript in una variabile String e voglio eseguirlo dal programma Java e passare qualche variabile ad esso. Se eseguo lo script R standalone, funziona perfettamente. Ho convertito lo script R per una linea da scampo tutto utilizzando programma Python come illustrato di seguito:non è in grado di eseguire lo script R dal programma java?

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 

Io uso la stringa stampato e memorizzarlo nella variabile stringa e poi sto eseguendo con sotto il codice e non funziona affatto Sto passando path e client_users variabile allo script R sopra.

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); 
} 

Sopra il codice funziona bene con lo script di shell bash. C'è qualcosa che devo fare speciale per lo script R? Userò lo stesso codice anche per script bash e script R.

E questo è l'errore che sto ottenendo:

/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')' 

E se tolgo commandList.add("/bin/bash"); e aggiungi commandList.add("/bin/Rscript"); poi vedi sotto errore:

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

Aggiornamento: -

Invece di usare il mio script sopra, ho deciso di usare uno script di inferno di stampa semplice in r per vedere se posso eseguirlo attraverso ugh Java o no.

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

Quando eseguire lo script con commandList.add("/bin/bash");, ottengo questo errore:

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

Ma se eseguo con questo commandList.add("/bin/sh");, ottengo questo errore:

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

risposta

3

Avrete per eseguire /usr/bin/Rscript direttamente. Inoltre, questo programma non leggere gli script da standard input (è necessario specificare il percorso dello script come argomento per Rscript), così si dovrà:

  • Creare un file temporaneo
  • Write lo script
  • eseguire il vostro script con rscript
  • cancellare i tuoi file temporaneo (come una buona pratica di programmazione)

a titolo di esempio, si tratta di un 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); 
} 

In alternativa, e se lo script ha un "shebang" come la prima linea, si potrebbe fare questi cambiamenti:

  • impostare il suo attributo eseguibile a "true"
  • uso il percorso del file tempor come primo elemento nella lista comandi (i. e.eliminare commandList.add("/usr/bin/Rscript");)

la parte del codice da modificare sarebbe:

... 

// 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); 

...