R中的错误处理:在函数错误时访问函数内的已知对象

Ant*_*ico 6 error-handling r

这是一个示例函数,假设我无法编辑它.

myfun <- function(){ x <- 1 ; stop( "error here" ) }
Run Code Online (Sandbox Code Playgroud)

stop()发生时,我将如何访问该对象x以查看它是什么?

不确定我是否应该使用这样的东西,或者我是否需要相关的东西dump.frames,或者如果不改变就不可能myfun()

withCallingHandlers( myfun() , error = function(e){ print( e ) } ) 
Run Code Online (Sandbox Code Playgroud)

我正在寻找类似于这种行为的东西,但需要在没有的情况下这样做 myfun()

myfun <- function(){ on.exit( print( x ) ) ; x <- 1 ; stop( "error here" ) }
myfun()
Run Code Online (Sandbox Code Playgroud)

对于我的用例,我无法更改,myfun()因为有大约50个函数,但我想知道错误时每个函数中一致命名的对象

谢谢!

dww*_*dww 6

选项1:

当然,您可以逐步使用这些功能browser(),但这可能会耗费您所需的时间.

选项2

虽然你说你无法改变myfun()的原因是"因为大约有50个函数",但这并不是一个不可逾越的障碍.R的一个强大功能是它可以编辑自己的功能.所以我们可以on.exit像这样添加对函数的调用:

body(myfun) <- as.call(c(as.name("{"), expression(on.exit(print(x))), body(myfun)))
Run Code Online (Sandbox Code Playgroud)

我们可以将它包装在一个方便的函数中,它不会像这样改变原始函数:

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

print.on.exit(myfun)
Run Code Online (Sandbox Code Playgroud)


Moo*_*per 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
Run Code Online (Sandbox Code Playgroud)

然后将它们的名字放入向量中,然后应用此代码,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
Run Code Online (Sandbox Code Playgroud)

然后恢复正常:

purrr::walk(funs,untrace)
Run Code Online (Sandbox Code Playgroud)

编辑

用上面的方法,x即使没有错误也会打印

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

要仅在错误时打印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
Run Code Online (Sandbox Code Playgroud)