From jeff.horner at vanderbilt.edu  Wed Feb  4 21:16:40 2009
From: jeff.horner at vanderbilt.edu (Jeffrey Horner)
Date: Wed, 04 Feb 2009 14:16:40 -0600
Subject: [Rd] Capturing all warnings (with messages)
In-Reply-To: <4989EA25.8050905@vanderbilt.edu>
References: <1F999E4C-B39B-46B4-92BC-074EFEE4B1E8@ucl.ac.uk>		<4989C7EA.1090700@vanderbilt.edu>	<68e086180902041011x53329634wf1b003c187090d3e@mail.gmail.com>
	<4989EA25.8050905@vanderbilt.edu>
Message-ID: <4989F7A8.6060707@vanderbilt.edu>

Jeffrey Horner wrote on 02/04/2009 01:19 PM:
> Jon Clayden wrote on 02/04/2009 12:11 PM:
>> 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.
> 
> So you want your program to handle all warnings your way, but you want 
> to continue execution after you have trapped the warnings. What 
> specifically do you want your program to do with a warning once you know 
> what it is?

I'm going to take a stab in the dark and presume you want to trap 
warnings  so that they aren't displayed. Using options(warn=-1) and the 
following could trap warnings allowing you to examine them and continue 
with code execution:

 > options('warn')
$warn
[1] -1

 > system('cat /tmp/foo.R')
warning("A simple warning")
cat("continuing...\n")
 > withCallingHandlers(source('/tmp/foo.R'), warning = function(e) str(e))
List of 2
  $ message: chr "A simple warning"
  $ call   : language eval.with.vis(expr, envir, enclos)
  - attr(*, "class")= chr [1:3] "simpleWarning" "warning" "condition"
continuing...

> 
> (I'd like to help you work through your problem to a solution because I 
> selfishly want to learn more about R's condition and restart system for 
> rapache's sake, my personal project. Right now, the way rapache notifies 
> users of R warnings and errors is crude but works.)
> 
> Jeff
> 
> 
>>
>> 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
>>>
> 
> 


-- 
http://biostat.mc.vanderbilt.edu/JeffreyHorner



[Rd] Capturing all warnings (with messages)
Jeffrey Horner