Error handling in R: access to a known object in a function during a function error

here's an example function, let's say I can't edit it.

myfun <- function(){ x <- 1 ; stop( "error here" ) }

when an event occurs stop(), how can I access the object xto find out what it was?

Not sure if I should use something like this or I need something related to dump.frames, or if this is simply not possible without changingmyfun()

withCallingHandlers( myfun() , error = function(e){ print( e ) } ) 

I am looking for something similar to this behavior, but you need to do it without myfun()

myfun <- function(){ on.exit( print( x ) ) ; x <- 1 ; stop( "error here" ) }
myfun()

for my use case, I cannot change myfun()because there are about fifty functions, but I want to know the sequentially called object in each of them during an error

thanks!

+6
4

trace. purr::walk, , sapply .

3 , 50:

myfun1 <- function(){ x <- 1 ; stop( "error here" ) }
myfun2 <- function(){ x <- 2 ; banana(2) }
myfun3 <- function(){ x <- 3 ; x <- "potatoe" + x }

myfun1() # Error in myfun1() : error here
myfun2() # Error in myfun2() : could not find function "banana"
myfun3() # Error in "potatoe" + x : non-numeric argument to binary operator

, x :

funs <- c("myfun1","myfun2","myfun3")
purrr::walk(funs,trace,exit = quote(print( x )))

myfun1() 
# Error in myfun1() : error here
# Tracing myfun1() on exit 
# [1] 1

myfun2()
# Error in myfun2() : could not find function "banana"
# Tracing myfun2() on exit 
# [1] 2

myfun3()
# Error in "potatoe" + x : non-numeric argument to binary operator
# Tracing myfun3() on exit 
# [1] 3

:

purrr::walk(funs,untrace)

x ,

myfun4 <- function(){ x <- 4 ; TRUE }
trace(myfun4, exit = quote(print( x )))
myfun4()
Tracing myfun4() on exit 
[1] 4
[1] TRUE

x , , , print FALSE , . x:

untrace(myfun4)
funs <- c("myfun1","myfun2","myfun3","myfun4") 
purrr::walk(funs,trace, print=FALSE,exit=quote(
  if(exists(".Traceback") && .Traceback[[length(.Traceback)]] == sys.calls()[[1]]){
    message("x at time of error:")
    print(x)}))

myfun3()
# Error in "potatoe" + x : non-numeric argument to binary operator
# x at time of error:
# [1] 3

myfun4()
# [1] TRUE
+2

1:

, , browser(), , .

2

, , myfun(), " ", . R , . on.exit , :

body(myfun) <- as.call(c(as.name("{"), expression(on.exit(print(x))), body(myfun)))

, :

print.on.exit = function(f, ...){
  body(f) <- as.call(c(as.name("{"), expression(on.exit(print(x))), body(f)))
  f(...)
}

print.on.exit(myfun)
+6

, , , , on.exit?

mylistofstate<-list()
fn <- function() {
  x <-1
    on.exit(mylistofstate["x"]<<-x, add=TRUE)
    stop()
}
fn()
 > Error in fn() : 
mylistofstate
 > $x
 >[1] 1
+1

myfun, , :

checkX <- function () { print(get("x", envir=parent.frame())) }
checkFun <- function (f) {
  eval(parse(text=c("on.exit(checkX())", deparse(body(f)))))
}

You can do checkXwhat you need to do, it can get full access to the function execution context with a call parent.frame().

myfun <- function(){ x <- 1 ; stop( "error here" ) }
checkFun(myfun)

To process functions with arguments, you can wrap an old function as follows:

wrapFun <- function (f) {
  eval(parse(text=c(deparse(args(f))[1], "{", "on.exit(checkX())", deparse(body(f)), "}")))
}

And call it with the necessary arguments:

myfun2 <- function(y){ x <- y + 1 ; stop( "error here" ) }
wrapFun(myfun2)(3)
+1
source

All Articles