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