2015-09-16 80 views
5

Mam Rscript w zmiennej String i chcę wykonać go z programu Java i przekazać niektóre zmienne do niego. Jeśli wykonam ten samodzielny skrypt R, działa dobrze. Mam przeliczone że skrypt R na jednej linii z wypadającymi to wszystko przy użyciu programu Pythona, jak pokazano poniżej:nie można wykonać skryptu R z programu 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 

używam drukowany napis na zewnątrz i zapisać go w zmiennej String, a następnie ja wykonując z poniżej kod i go w ogóle nie działa. Przechodzę pod zmienną path i client_users do powyższego skryptu 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); 
} 

Powyższy kod działa dobrze ze skryptem powłoki bash. Czy jest coś, co muszę zrobić specjalnie dla skryptu R? Będę używał tego samego kodu również dla skryptów Bash i R.

I to jest błąd otrzymuję:

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

A jeśli usunąć commandList.add("/bin/bash"); i dodać commandList.add("/bin/Rscript"); potem patrz poniżej błędu:

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

UPDATE: -

Zamiast używać powyższego skryptu, zdecydowałem się użyć prostego skryptu piekła druku w r, aby sprawdzić, czy mogę go wykonać ugh Java czy nie.

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

Kiedy wykonać ten skrypt z commandList.add("/bin/bash");, otrzymuję ten błąd:

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

Ale gdybym wykonać z tego commandList.add("/bin/sh");, otrzymuję ten błąd:

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

Odpowiedz

3

Będziesz mieć bezpośrednio uruchomić /usr/bin/Rscript. Ponadto, program ten nie czyta skrypty ze standardowego wejścia (trzeba podać ścieżkę do skryptu jako argument dla Rscript), więc trzeba będzie:

  • Utwórz plik temp
  • Write skrypt
  • Wykonaj skrypt z Rscript
  • Usuń plik tymczasowy (jako dobrej praktyki programowania)

jako przykład, jest to 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); 
} 

Jako alternatywę i jeśli skrypt ma „shebang” jako pierwszej linii, można zrobić te zmiany:

  • ustawić jego atrybut wykonywalny na „true”
  • korzystania ścieżka do pliku tymczasowego jako pierwszy element w liście poleceń (i. mi.usuwać commandList.add("/usr/bin/Rscript");)

część kodu zostać zmodyfikowany byłoby:

... 

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

... 
Powiązane problemy