here's a example function, let's say i'm unable able to edit it.
myfun <- function(){ x <- 1 ; stop( "error here" ) }
when the stop()
occurs, how would i access the object x
to see what it was?
not sure if i should use something like this, or if i need something related to dump.frames
, or if this is simply not possible without changing myfun()
withCallingHandlers( myfun() , error = function(e){ print( e ) } )
i am looking for something similar to this behavior, but need to do it without myfun()
myfun <- function(){ on.exit( print( x ) ) ; x <- 1 ; stop( "error here" ) }
myfun()
for my use-case, i am unable to change myfun()
because there are about fifty functions, but i want to know a consistently-named object within each of them at time of error
thanks!
Option 1:
You could, of course, step through the functions using browser()
, but this may be too time consuming for what you want.
Option 2
Although you say that the reason you are unable to change myfun() is "because there are about fifty functions", this does not present an insurmountable barrier. One of the powerful things about R is that it can edit its own functions. So we can add an on.exit
call to the function like this:
body(myfun) <- as.call(c(as.name("{"), expression(on.exit(print(x))), body(myfun)))
We can wrap this in a handy function which does not change the original function like this:
print.on.exit = function(f, ...){
body(f) <- as.call(c(as.name("{"), expression(on.exit(print(x))), body(f)))
f(...)
}
print.on.exit(myfun)
Here's a way to do it with trace
. I use also purr::walk
as it is silent but you can use sapply
instead for the same effect.
First let's define 3 functions, as you have 50 of them:
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
Then put their names in a vector, and just apply this code, that will print x
whenever exiting the function :
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
And then get back to normal:
purrr::walk(funs,untrace)
EDIT
With method above, x
will be printed even when there's no error
myfun4 <- function(){ x <- 4 ; TRUE }
trace(myfun4, exit = quote(print( x )))
myfun4()
Tracing myfun4() on exit
[1] 4
[1] TRUE
To print x
only on error, you can use following code, by the same token I've set print
parameter to FALSE
for lighter display and made it clearer than the printed value in case of error was 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With