Skip to content

type="message" possibility for capture.output() ?

2 messages · Ben Bolker, Brian Ripley

#
As far as I can tell, there's no built-in way to get
capture.output() to capture messages (stderr) instead of
stdout ... suggested, fairly trivial, patch below.

f <- function() {
    message("abc")
    cat("def\n")
}

x <- capture.output(f())
## prints 'abc'
x ## value: "def"

source("~/R/r-devel/src/library/utils/R/capture.output.R")
x <- capture.output(f()) ## unchanged
x <- capture.output(f(),type="message") ## prints 'def': value 'abc'

   Of course, if someone was going to mess with this function more,
it might be nice to have an option to have *both* streams captured ...

Index: capture.output.R
===================================================================
--- capture.output.R	(revision 63969)
+++ capture.output.R	(working copy)
@@ -16,8 +16,10 @@
 #  A copy of the GNU General Public License is available at
 #  http://www.r-project.org/Licenses/

-capture.output <- function(..., file=NULL, append=FALSE)
+capture.output <- function(..., file=NULL, append=FALSE,
+                           type = c("output", "message"))
 {
+    type <- match.arg(type)
     args <- substitute(list(...))[-1L]

     rval <- NULL; closeit <- TRUE
@@ -31,9 +33,9 @@
     } else
         stop("'file' must be NULL, a character string or a connection")

-    sink(file)
+    sink(file,type=type)
     ## for error recovery: all output will be lost if file=NULL
-    on.exit({sink(); if(closeit) close(file)})
+    on.exit({sink(type=type); if(closeit) close(file)})

     pf <- parent.frame()
     evalVis <- function(expr)
@@ -50,7 +52,7 @@
     }
     ## we need to close the text connection before returning 'rval'
     on.exit()
-    sink()
+    sink(type=type)
     if(closeit) close(file)
     if(is.null(rval)) invisible(NULL) else rval
 }
#
That is not safe ... you should at least check if the message stream is 
not already diverted. As the help says:

      Sink-ing the messages stream should be done only with great care.
      For that stream ?file? must be an already open connection, and
      there is no stack of connections.

which seems sufficient warning not to make this any easier (and is why 
it had not been implemented in the past -- it has been discussed).  If 
you have code that you want to run and capture all the output from, it 
is preferable to run it in a separate process and there are lots of 
examples of that in the 'tools' package.
On 22/09/2013 18:03, Ben Bolker wrote: