Захватить состояние выхода и выход из системного вызова в R - PullRequest
17 голосов
/ 10 августа 2011

Я немного поигрался с system() и system2() для удовольствия, и меня поразило, что я могу сохранить либо выходной, либо выходной статус в объекте.Пример с игрушкой:

X <- system("ping google.com",intern=TRUE)

дает мне вывод, тогда как

X <- system2("ping", "google.com")

дает мне статус выхода (1 в данном случае, Google не пингует).Если я хочу и выход, и статус выхода, мне нужно сделать 2 системных вызова, что кажется излишним.Как я могу получить оба с использованием только одного системного вызова?

РЕДАКТИРОВАТЬ: Я хотел бы иметь оба в консоли, если это возможно, не просматривая временный файл с использованием stdout="somefile.ext" в вызове system2и впоследствии читая это в.

Ответы [ 3 ]

12 голосов
/ 11 августа 2011

Меня немного смущает ваше описание system2, потому что оно имеет аргументы stdout и stderr.Таким образом, он может возвращать статус выхода, стандартный вывод и стандартный вывод.

> out <- tryCatch(ex <- system2("ls","xx", stdout=TRUE, stderr=TRUE), warning=function(w){w})
> out
<simpleWarning: running command ''ls' xx 2>&1' had status 2>
> ex
[1] "ls: cannot access xx: No such file or directory"
> out <- tryCatch(ex <- system2("ls","-l", stdout=TRUE, stderr=TRUE), warning=function(w){w})
> out
 [listing snipped]                  
> ex
 [listing snipped]
11 голосов
/ 17 мая 2012

Начиная с R 2.15, system2 будет возвращать значение в качестве атрибута, когда stdout и / или stderr равны ИСТИНА.Это облегчает получение вывода текста и возвращаемого значения.

В этом примере ret заканчивается строкой с атрибутом "status":

> ret <- system2("ls","xx", stdout=TRUE, stderr=TRUE)
Warning message:
running command ''ls' xx 2>&1' had status 1 
> ret
[1] "ls: xx: No such file or directory"
attr(,"status")
[1] 1
> attr(ret, "status")
[1] 1
5 голосов
/ 13 июня 2013

Я предлагаю использовать эту функцию здесь:

robust.system <- function (cmd) {
  stderrFile = tempfile(pattern="R_robust.system_stderr", fileext=as.character(Sys.getpid()))
  stdoutFile = tempfile(pattern="R_robust.system_stdout", fileext=as.character(Sys.getpid()))

  retval = list()
  retval$exitStatus = system(paste0(cmd, " 2> ", shQuote(stderrFile), " > ", shQuote(stdoutFile)))
  retval$stdout = readLines(stdoutFile)
  retval$stderr = readLines(stderrFile)

  unlink(c(stdoutFile, stderrFile))
  return(retval)
}

Это будет работать только на Unix-подобной оболочке, которая принимает нотации> и 2>, и аргумент cmd не должен перенаправлять сам вывод.Но это делает трюк:

> robust.system("ls -la")
$exitStatus
[1] 0

$stdout
 [1] "total 160"                                                      
 [2] "drwxr-xr-x  14 asieira  staff    476 10 Jun 18:18 ."            
 [3] "drwxr-xr-x  12 asieira  staff    408  9 Jun 20:13 .."           
 [4] "-rw-r--r--   1 asieira  staff   6736  5 Jun 19:32 .Rapp.history"
 [5] "-rw-r--r--   1 asieira  staff  19109 11 Jun 20:44 .Rhistory"    

$stderr
character(0)
...