Philippe Grosjean
2006-Jun-25 17:43 UTC
[Rd] using withCallingHandlers, how to deal with warning( , immediate. = TRUE)?
Hello,
I want to use withCallingHandlers(expr, warning = function(w) { ....}),
that is, to use a custom warning handler. I want this handler to
replicate the behavior of the usual handler. I have problems with the
mode 'options(warn = 0)' where the warnings are delayed, except if
calling 'warning("message", immediate. = TRUE). Indeed, if my
custom
warning handler manages to delay the display of warning messages, it
cannot detect if the argument immediate. = TRUE was use, and thus, it
cannot behave consequently.
Here is a toy example to illustrate my problem (whole script at the end
of this message):
> # This is what I want to replicate in my own handler:
> options(warn = 0)
> options(warning.expression = NULL)
> for (i in 1:3) {
+ print(i)
+ warning("test", immediate. = (i < 2))
+ }
[1] 1
Warning: test
[1] 2
[1] 3
Warning messages:
1: test
2: test
# First warning is NOT delayed, but the others are
Here is what I could use if I do not delay printing of warnings:
> options(warning.expression = NULL)
> options(warning.expression = expression()) # Disable normal warnings
> withCallingHandlers(for (i in 1:3) {print(i);
+ warning("test", immediate. = (i < 2))},
+ warning = function(w)
+ cat("Warning:", conditionMessage(w), "\n"))
[1] 1
Warning: test
[1] 2
Warning: test
[1] 3
Warning: test
> options(warning.expression = NULL)
It gets a little bit more complex to delay handling of warning messages,
but basically, I manage it that way:
> options(warning.expression = NULL)
> options(warning.expression = NULL)
> options(warning.expression = expression()) # Disable normal warnings
> if (exists("last.warning", envir = .GlobalEnv))
+ rm("last.warning", envir = .GlobalEnv)
> withCallingHandlers(for (i in 1:3) {print(i);
+ warning("test", immediate. = (i < 2))},
+ warning = function(w) {
+ if (exists("last.warning", envir = .GlobalEnv)) {
+ lwarn <- get("last.warning", envir = .GlobalEnv)
+ } else lwarn <- list()
+ # Do not add more than 50 warnings
+ if (length(lwarn) >= 50) return()
+ # Add the warning to this list
+ nwarn <- length(lwarn)
+ names.warn <- names(lwarn)
+ Call <- conditionCall(w)
+ lwarn[[nwarn + 1]] <- Call
+ names(lwarn) <- c(names.warn, conditionMessage(w))
+ # Save the modified version in .GlobalEnv
+ last.warning <<- lwarn
+ })
[1] 1
[1] 2
[1] 3
> invisible(warnings()) # Now display delayed warnings()
Warning messages:
1: test in: withCallingHandlers(for (i in 1:3) { ...
2: test in: withCallingHandlers(for (i in 1:3) { ...
3: test in: withCallingHandlers(for (i in 1:3) { ...
> options(warning.expression = NULL)
Now, obviously, I need a mechanism to detect if 'immediate. = TRUE' was
used in warning(), in order to delay or not accordingly, and replicate
exactly the example above... BUT... I have no idea at all where I can
find this information! Could someone help me, please?
Best,
Philippe Grosjean
P.S.: here is the complete script of the toy example:
### The example we want to replicate with our own handler
options(warn = 0)
options(warning.expression = NULL)
for (i in 1:3) {
print(i)
warning("test", immediate. = (i < 2))
}
### A custom warning handler that does NOT delay warning messages
options(warning.expression = NULL)
options(warning.expression = expression()) # Disable normal warnings
withCallingHandlers(for (i in 1:3) {print(i);
warning("test", immediate. = (i < 2))},
warning = function(w)
cat("Warning:", conditionMessage(w), "\n"))
options(warning.expression = NULL)
### A custom warning handler that ALWAYS delays warning messages
options(warning.expression = NULL)
options(warning.expression = expression()) # Disable normal warnings
if (exists("last.warning", envir = .GlobalEnv))
rm("last.warning", envir = .GlobalEnv)
withCallingHandlers(for (i in 1:3) {print(i);
warning("test", immediate. = (i < 2))},
warning = function(w) {
if (exists("last.warning", envir = .GlobalEnv)) {
lwarn <- get("last.warning", envir = .GlobalEnv)
} else lwarn <- list()
# Do not add more than 50 warnings
if (length(lwarn) >= 50) return()
# Add the warning to this list
nwarn <- length(lwarn)
names.warn <- names(lwarn)
Call <- conditionCall(w)
lwarn[[nwarn + 1]] <- Call
names(lwarn) <- c(names.warn, conditionMessage(w))
# Save the modified version in .GlobalEnv
last.warning <<- lwarn
})
invisible(warnings()) # Now display delayed warnings()
options(warning.expression = NULL)
### How do I write my handler that delays only when warn = 0 and
### immediate. = FALSE in the calling of warning() ???
# ...?
Luke Tierney
2006-Jun-27 13:26 UTC
[Rd] using withCallingHandlers, how to deal with warning( , immediate. = TRUE)?
I don't think there is currently any way of identifying the immediate. = TRUE calls short of walking up the call stack with the appropriate sys.xyz functions. A better design would have been for calls with immediate. = TRUE to signal warnings of a subclass of simpleWarning, say immediateSimpleWarning, so these can be caught and handled more reasonably. I'll make a note to look into this. Best, luke On Sun, 25 Jun 2006, Philippe Grosjean wrote:> Hello, > > I want to use withCallingHandlers(expr, warning = function(w) { ....}), > that is, to use a custom warning handler. I want this handler to > replicate the behavior of the usual handler. I have problems with the > mode 'options(warn = 0)' where the warnings are delayed, except if > calling 'warning("message", immediate. = TRUE). Indeed, if my custom > warning handler manages to delay the display of warning messages, it > cannot detect if the argument immediate. = TRUE was use, and thus, it > cannot behave consequently. > > Here is a toy example to illustrate my problem (whole script at the end > of this message): > > > # This is what I want to replicate in my own handler: > > options(warn = 0) > > options(warning.expression = NULL) > > for (i in 1:3) { > + print(i) > + warning("test", immediate. = (i < 2)) > + } > [1] 1 > Warning: test > [1] 2 > [1] 3 > Warning messages: > 1: test > 2: test > # First warning is NOT delayed, but the others are > > Here is what I could use if I do not delay printing of warnings: > > > options(warning.expression = NULL) > > options(warning.expression = expression()) # Disable normal warnings > > withCallingHandlers(for (i in 1:3) {print(i); > + warning("test", immediate. = (i < 2))}, > + warning = function(w) > + cat("Warning:", conditionMessage(w), "\n")) > [1] 1 > Warning: test > [1] 2 > Warning: test > [1] 3 > Warning: test > > options(warning.expression = NULL) > > It gets a little bit more complex to delay handling of warning messages, > but basically, I manage it that way: > > > options(warning.expression = NULL) > > options(warning.expression = NULL) > > options(warning.expression = expression()) # Disable normal warnings > > if (exists("last.warning", envir = .GlobalEnv)) > + rm("last.warning", envir = .GlobalEnv) > > withCallingHandlers(for (i in 1:3) {print(i); > + warning("test", immediate. = (i < 2))}, > + warning = function(w) { > + if (exists("last.warning", envir = .GlobalEnv)) { > + lwarn <- get("last.warning", envir = .GlobalEnv) > + } else lwarn <- list() > + # Do not add more than 50 warnings > + if (length(lwarn) >= 50) return() > + # Add the warning to this list > + nwarn <- length(lwarn) > + names.warn <- names(lwarn) > + Call <- conditionCall(w) > + lwarn[[nwarn + 1]] <- Call > + names(lwarn) <- c(names.warn, conditionMessage(w)) > + # Save the modified version in .GlobalEnv > + last.warning <<- lwarn > + }) > [1] 1 > [1] 2 > [1] 3 > > invisible(warnings()) # Now display delayed warnings() > Warning messages: > 1: test in: withCallingHandlers(for (i in 1:3) { ... > 2: test in: withCallingHandlers(for (i in 1:3) { ... > 3: test in: withCallingHandlers(for (i in 1:3) { ... > > options(warning.expression = NULL) > > Now, obviously, I need a mechanism to detect if 'immediate. = TRUE' was > used in warning(), in order to delay or not accordingly, and replicate > exactly the example above... BUT... I have no idea at all where I can > find this information! Could someone help me, please? > Best, > > Philippe Grosjean > > P.S.: here is the complete script of the toy example: > > ### The example we want to replicate with our own handler > options(warn = 0) > options(warning.expression = NULL) > for (i in 1:3) { > print(i) > warning("test", immediate. = (i < 2)) > } > > ### A custom warning handler that does NOT delay warning messages > options(warning.expression = NULL) > options(warning.expression = expression()) # Disable normal warnings > withCallingHandlers(for (i in 1:3) {print(i); > warning("test", immediate. = (i < 2))}, > warning = function(w) > cat("Warning:", conditionMessage(w), "\n")) > options(warning.expression = NULL) > > ### A custom warning handler that ALWAYS delays warning messages > options(warning.expression = NULL) > options(warning.expression = expression()) # Disable normal warnings > if (exists("last.warning", envir = .GlobalEnv)) > rm("last.warning", envir = .GlobalEnv) > withCallingHandlers(for (i in 1:3) {print(i); > warning("test", immediate. = (i < 2))}, > warning = function(w) { > if (exists("last.warning", envir = .GlobalEnv)) { > lwarn <- get("last.warning", envir = .GlobalEnv) > } else lwarn <- list() > # Do not add more than 50 warnings > if (length(lwarn) >= 50) return() > # Add the warning to this list > nwarn <- length(lwarn) > names.warn <- names(lwarn) > Call <- conditionCall(w) > lwarn[[nwarn + 1]] <- Call > names(lwarn) <- c(names.warn, conditionMessage(w)) > # Save the modified version in .GlobalEnv > last.warning <<- lwarn > }) > invisible(warnings()) # Now display delayed warnings() > options(warning.expression = NULL) > > ### How do I write my handler that delays only when warn = 0 and > ### immediate. = FALSE in the calling of warning() ??? > # ...? > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >-- Luke Tierney Chair, Statistics and Actuarial Science Ralph E. Wareham Professor of Mathematical Sciences University of Iowa Phone: 319-335-3386 Department of Statistics and Fax: 319-335-3017 Actuarial Science 241 Schaeffer Hall email: luke at stat.uiowa.edu Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu