Захват статуса выхода и выхода из системного вызова в R
Я немного играл с system()
и system2()
для удовольствия, и мне показалось, что я могу сохранить либо выход, либо статус выхода в объекте. Пример игрушки:
X <- system("ping google.com",intern=TRUE)
дает мне результат, тогда как
X <- system2("ping", "google.com")
дает мне статус выхода (1 в этом случае, google не выполняет пинг). Если я хочу как выход, так и статус выхода, я должен сделать 2 системных вызова, которые кажутся немного переборщиками. Как я могу получить оба с использованием только одного системного вызова?
EDIT: я хотел бы иметь как на консоли, если возможно, не переходя временный файл с помощью stdout="somefile.ext"
в вызове system2
и последующего его чтения.
Ответы
Ответ 1
Как и в случае R 2.15, system2
даст возвращаемое значение как атрибут, когда stdout
и/или stderr
имеют значение TRUE. Это облегчает получение выходного текста и возвращаемое значение.
В этом примере 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
Ответ 2
Я немного смущен вашим описанием system2, потому что у него есть аргументы stdout и stderr. Таким образом, он может возвращать оба статуса выхода, 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]
Ответ 3
Я предлагаю использовать эту функцию здесь:
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)