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

时间:2014-08-14 11:20:45

标签: r stdout message stderr

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

message手册说明:

  

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

所以问题是如何更改此默认行为?仍然保留warning()stop()的重定向。

已尝试接收type='message'但它会重定向所有(消息,警告,错误)。

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

print("using print")
cat("using cat\n")
message("using message")
warning("using warning")
stop("using stop")
q("no")

然后将执行:

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

我不知道如何使用2>&1,因为我的脚本产生了大量的message,很少出现真正的错误,因此我需要将这些日志存储在单独的文件中。

4 个答案:

答案 0 :(得分: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()
}

答案 1 :(得分:2)

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的内容重定向到您的persistent.log
  4. 然后删除temp.log

答案 2 :(得分:1)

使用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")

答案 3 :(得分:0)

将@Thomas和@ branch14的答案结合在一起,这就是我想出的:

.stderr_message <- message
message <- function(...) {
    sink(stdout(), type = "message")
    .stderr_message(...)
    sink(NULL, type = "message")
}

我使用此代码在外壳上对此进行了验证

.stderr_message <- message
message <- function(...) {
    sink(stdout(), type = "message")
    .stderr_message(...)
    sink(NULL, type = "message")
}

print(1)
message(1)

没有我的message()

> Rscript bug.R 2> >(sed 's/^/stderr: /') > >(sed 's/^/stdout: /')
stdout: [1] 1
stderr: 1
> Rscript bug.R 2> >(sed 's/^/stderr: /') > >(sed 's/^/stdout: /')
stdout: [1] 1
stdout: 1