将 R 诊断消息发送到 stdout 而不是 stderr

jan*_*cki 8 message r stdout stderr

寻找一个选项,让我将 R 诊断消息(由 产生message())重定向到stdout,而不是stderr默认情况下。

message 手册指出:

默认处理程序将消息发送到 stderr() 连接。

所以问题是我怎样才能改变这个默认行为?仍然保持重定向warning()stop()完好无损。

已经尝试过 sinktype='message'但它重定向了所有(消息、警告、错误)。

如果有人愿意测试,这是示例脚本exec_test.R

print("using print")
cat("using cat\n")
message("using message")
warning("using warning")
stop("using stop")
q("no")
Run Code Online (Sandbox Code Playgroud)

然后将通过以下方式执行:

Rscript exec_test.R 1>> exec_test.Rout 2>> exec_test_error.Rout

我不知道要使用什么,2>&1因为我的脚本会产生大量的messages 并且很少产生真正的错误,所以我需要将这些日志存储在单独的文件中。

Tho*_*mas 5

使用sink. 这是对您的代码的修改:

sink(stdout(), type = "message") # sink messages to stdout
print("using print")
cat("using cat\n")
message("using message")
warning("using warning")
sink(NULL, type="message") # close the sink
warning("after ending sink") # this will be the only thing in your err file
q("no")
Run Code Online (Sandbox Code Playgroud)


Ste*_*mer 5

OP 显示了通过 Rscript 命令并使用一些 I/O 重定向进行的执行。如果您想使用重定向来记录所有内容并仅在出现错误时显示到控制台,我发现的最佳方法是||在打印到屏幕之前检查脚本是否具有非零退出状态:

Rscript myrscript.R > temp.log 2>&1 || cat temp.log

此方法严格依赖于打印的退出代码,该代码仅部分绕过了message()stderr,但我认为这个示例有助于提及,因为消息不一定会触发非零退出状态,您可以继续使用此安静地记录方法。

如果您想更进一步并继续附加到单个日志文件,那么这将起作用:

Rscript myrscript.R > temp.log 2>&1 || cat temp.log && cat temp.log >> persistent.log && rm temp.log

该命令的伪代码是:

  1. 重定向stderrstdout进入 temp.log
  2. 如果命令具有非零退出状态,则写入屏幕
  3. 然后将 temp.log 的内容重定向到您的 permanent.log 中
  4. 然后删除temp.log


bra*_*h14 2

虽然这很可能不是最佳实践,但您可以使用默认message写入的版本进行覆盖,对吧?stdout()

message <- function (..., domain = NULL, appendLF = TRUE) 
{
    args <- list(...)
    cond <- if (length(args) == 1L && inherits(args[[1L]], "condition")) {
        if (nargs() > 1L) 
            warning("additional arguments ignored in message()")
        args[[1L]]
    }
    else {
        msg <- .makeMessage(..., domain = domain, appendLF = appendLF)
        call <- sys.call()
        simpleMessage(msg, call)
    }
    defaultHandler <- function(c) {
        cat(conditionMessage(c), file = stdout(), sep = "")
    }
    withRestarts({
        signalCondition(cond)
        defaultHandler(cond)
    }, muffleMessage = function() NULL)
    invisible()
}
Run Code Online (Sandbox Code Playgroud)