send R diagnostic messages to stdout instead stderr

前端 未结 4 1550
醉梦人生
醉梦人生 2020-12-31 23:13

Looking for an options which let me to redirect R diagnostic messages (produces by message()) to stdout, not stderr as it is by defaul

相关标签:
4条回答
  • 2020-12-31 23:41

    While this is very likely not a best practice, you could override message with a version that writes to stdout() by default, right?

    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()
    }
    
    0 讨论(0)
  • 2020-12-31 23:46

    Using sink. Here's a modification of your code:

    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")
    
    0 讨论(0)
  • 2020-12-31 23:59

    Combining @Thomas and @branch14's answers into one, this is what I came up with:

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

    I verified this on the shell using this code

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

    Without my 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
    
    0 讨论(0)
  • 2021-01-01 00:00

    The OP showed the execution happening via the Rscript command and using some I/O redirection. If you want to use redirection to log everything and only show to console on error, the best method I've found is to use || to check if the script had non-zero exit status before printing to screen:

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

    This method relies strictly on the exit code for printing, which only partly gets around message() going to stderr, but I thought this example helpful to mention since messages won't necessarily trigger a non-zero exit status and you can continue to log quietly with this method.

    If you'd like to go one step further and keep appending to a single log file, then this will work:

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

    The pseudocode for this command is:

    1. Redirect stderr and stdout into temp.log
    2. If command had non-zero exit status then write to screen
    3. Then redirect the contents of temp.log into your persistent.log
    4. Then remove temp.log
    0 讨论(0)
提交回复
热议问题