这是一个示例函数,假设我无法编辑它。
ToolbarItems
当myfun <- function(){ x <- 1 ; stop( "error here" ) }
发生时,我如何访问对象stop()
以查看它是什么?
不确定我是否应该使用类似的内容,或者我需要与x
相关的内容,或者如果不改变dump.frames
myfun()
我正在寻找类似于此行为的内容,但需要在没有withCallingHandlers( myfun() , error = function(e){ print( e ) } )
myfun()
对于我的用例,我无法更改myfun <- function(){ on.exit( print( x ) ) ; x <- 1 ; stop( "error here" ) }
myfun()
,因为大约有50个函数,但我想在错误发生时知道每个函数中一致命名的对象
谢谢!
答案 0 :(得分:6)
选项1:
当然,您可以使用browser()
逐步执行这些功能,但这可能会耗费您所需的时间。
选项2
虽然你说你无法改变myfun()的原因是&#34;因为大约有50个函数&#34;,这并不是一个不可逾越的障碍。 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)
答案 1 :(得分:2)
这是使用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)
我尝试回答但是我不确定你想要什么,你能编辑你的函数来添加on.exit吗? :
mylistofstate<-list()
fn <- function() {
x <-1
on.exit(mylistofstate["x"]<<-x, add=TRUE)
stop()
}
fn()
> Error in fn() :
mylistofstate
> $x
>[1] 1
答案 3 :(得分:1)
此方法允许访问myfun
的执行环境,而无需重写:
checkX <- function () { print(get("x", envir=parent.frame())) }
checkFun <- function (f) {
eval(parse(text=c("on.exit(checkX())", deparse(body(f)))))
}
您可以checkX
执行您需要的操作,通过parent.frame()
调用可以完全访问函数的执行上下文。
myfun <- function(){ x <- 1 ; stop( "error here" ) }
checkFun(myfun)
要使用参数处理函数,可以使用以下函数包装旧函数:
wrapFun <- function (f) {
eval(parse(text=c(deparse(args(f))[1], "{", "on.exit(checkX())", deparse(body(f)), "}")))
}
用你想要的参数调用它:
myfun2 <- function(y){ x <- y + 1 ; stop( "error here" ) }
wrapFun(myfun2)(3)