From j.clayden at ucl.ac.uk  Wed Feb  4 19:11:56 2009
From: j.clayden at ucl.ac.uk (Jon Clayden)
Date: Wed, 4 Feb 2009 18:11:56 +0000
Subject: [Rd] Capturing all warnings (with messages)
In-Reply-To: <4989C7EA.1090700@vanderbilt.edu>
References: <1F999E4C-B39B-46B4-92BC-074EFEE4B1E8@ucl.ac.uk>
	<4989C7EA.1090700@vanderbilt.edu>
Message-ID: <68e086180902041011x53329634wf1b003c187090d3e@mail.gmail.com>

Dear Jeff,

Many thanks for the suggestion, but I don't think tryCatch() is the
answer, mainly because it causes code to stop executing when a warning
is signalled:

> f <- function(w) print(w$message)
> tryCatch({warning("Test"); print(3)},warning=f)
[1] "Test"

(The "print(3)" call is not run.) In this regard,
withCallingHandlers() is preferable. But either way it is untidy, at
best, to routinely put code inside one of these functions when I know
I always want to handle warnings my way. If I could set an appropriate
option when a package is loaded, or in an .Rprofile, then I should
never need to worry about whether a bit of code might generate
warnings and so should be wrapped.

Regards,
Jon

2009/2/4 Jeffrey Horner <jeff.horner at vanderbilt.edu>:
> Jon Clayden wrote on 02/04/2009 06:59 AM:
>>
>> Dear all,
>>
>> For an open-source project that I'm working on (1), which uses R for all
>> its heavy lifting but includes a wrapper shell script, I was hoping to find
>> a way to capture all warnings (and, in fact, errors too), and handle them in
>> my own way. I realise I can do this for a single expression using something
>> like:
>>
>>  > f <- function(w) print(w$message)
>>  > withCallingHandlers(warning("Test"),warning=f)
>> [1] "Test"
>> Warning message:
>> In withCallingHandlers(warning("Test"), warning = f) : Test
>>
>> But I would like to capture all warnings, globally. The
>> "warning.expression" option doesn't seem to allow an argument, and I can't
>> seem to use "last.warning" to get at the message either:
>>
>>  > g <- function() print(last.warning$message)
>>  > options(warning.expression=quote(g()))
>>  > warning("Test2")
>> NULL
>>
>> Could anyone tell me whether there's a way to do this, please? An old
>> thread on this topic seemed to go unresolved (2), and I've skimmed RNEWS and
>> I don't see anything about this since then.
>
> In fact, the thread did have the answer: tryCatch(). The help page is a bear
> to read and comprehend, but if you do invest the time it should convince you
> that you will want to use it. I find that I have to read and reread many
> sections of R documentation before I can reconcile what I want to know with
> what the authors are trying to tell me.
>
> I don't comprehend everything about R's condition system, but let me see if
> I can convince you that you need tryCatch() to do what you want.
>
> Consider:
>
> x <- function() warning("warning message")
> y <- function() call_unknown_fun()
> z <- function() message('message message')
>
> Each of these functions signal conditions of a particular condition class:
> simpleWarning, simpleError, and simpleMessage, respectively.
>
> w <- function(e) str(e)
>
> I'm going to use w  to trap the simpleWarning condition:
>
>> tryCatch(x(),simpleWarning=w)
> List of 2
>  $ message: chr "warning message"
>  $ call   : language x()
>  - attr(*, "class")= chr [1:3] "simpleWarning" "warning" "condition"
>
> So tryCatch returned a list with two elements, the message and the call that
> signaled the condition. In fact the list is actually an S3 object of class
> simpleWarning, which inherits from warning and condition. Reading the help
> page for tryCatch(), I can actually do this:
>
>> tryCatch(x(),condition=w)
> List of 2
>  $ message: chr "warning message"
>  $ call   : language x()
>  - attr(*, "class")= chr [1:3] "simpleWarning" "warning" "condition"
>
> since simpleWarning inherits from condition. And in fact I can use the
> condition class to trap everything I want.
>
>> tryCatch(y(),condition=w)
> List of 2
>  $ message: chr "could not find function \"call_unknown_fun\""
>  $ call   : language y()
>  - attr(*, "class")= chr [1:3] "simpleError" "error" "condition"
>
>> tryCatch(z(),condition=w)
> List of 2
>  $ message: chr "message message\n"
>  $ call   : language message("message message")
>  - attr(*, "class")= chr [1:3] "condition" "message" "simpleMessage"
>
> (Side note: is the class hierarchy actually correct for this simpleMessage
> object?)
>
> So in summary, wrap every R expression you want to run within a single
> tryCatch() call and trap all conditions with one handler for the abstract
> class named 'condition'. I think that's what you want...
>
> Jeff
>
>
>>
>>  > sessionInfo()
>> R version 2.8.1 (2008-12-22)
>> i386-apple-darwin8.11.1
>>
>> locale:
>> en_GB.UTF-8/en_US.UTF-8/C/C/en_GB.UTF-8/en_GB.UTF-8
>>
>> attached base packages:
>> [1] stats     graphics  grDevices utils     datasets  splines   methods
>> [8] base
>>
>> other attached packages:
>> [1] tractor.session_1.0.0   tractor.base_1.0.3      tractor.nt_1.0.2
>>
>> loaded via a namespace (and not attached):
>> [1] tools_2.8.1
>>
>> Regards,
>> Jon
>>
>>
>> (1) http://code.google.com/p/tractor/
>> (2) http://finzi.psych.upenn.edu/R/Rhelp02/archive/61872.html
>>
>>
>> --
>> Jonathan D. Clayden, Ph.D.
>> Research Fellow
>> Radiology and Physics Unit
>> UCL Institute of Child Health
>> 30 Guilford Street
>> LONDON  WC1N 1EH
>> United Kingdom
>>
>> t | +44 (0)20 7905 2708
>> f | +44 (0)20 7905 2358
>> w | www.homepages.ucl.ac.uk/~sejjjd2/
>>
>> ______________________________________________
>> R-devel at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>
>
> --
> http://biostat.mc.vanderbilt.edu/JeffreyHorner
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>



[Rd] Capturing all warnings (with messages)
Jon Clayden