【问题标题】:Save traceback on error using tryCatch使用 tryCatch 保存错误回溯
【发布时间】:2013-06-02 04:37:33
【问题描述】:

在我的 webapp 中调用 R 函数时,我想在发生错误时捕获堆栈跟踪并将其呈现给用户以进行调试。类似于traceback() 在交互式会话中的输出。但是,traceback 在错误处理程序中调用时似乎不起作用,它返回No traceback available

f <- function() {
    g <- function() stop("test traceback")
    g()
}

errhandler <- function(e){
  stacktrace <- traceback()
  unlist(stacktrace);
}

out <- tryCatch(f(), error=errhandler) 

有什么方法可以通过编程捕获错误的堆栈跟踪? IE。获取错误后手动调用traceback() 时会得到的输出:

f()
traceback()

【问题讨论】:

    标签: r stack-trace cran


    【解决方案1】:

    事实证明,最新版本的evaluate 包有一个名为try_capture_stack 的函数,这是一个漂亮的good implementation

    【讨论】:

    • 使用 .try_quietly 的不良副作用是什么?
    【解决方案2】:

    我没有像try_capture_stack 那样获得堆栈,所以我编写了一个类似于try 的解决方案,除了它还返回调用堆栈。 tools:::.try_quietly 很整洁,但没有保存堆栈以供以后检查...

    tryStack <- function(
    expr,
    silent=FALSE
    )
    {
    tryenv <- new.env()
    out <- try(withCallingHandlers(expr, error=function(e)
      {
      stack <- sys.calls()
      stack <- stack[-(2:7)]
      stack <- head(stack, -2)
      stack <- sapply(stack, deparse)
      if(!silent && isTRUE(getOption("show.error.messages"))) 
        cat("This is the error stack: ", stack, sep="\n")
      assign("stackmsg", value=paste(stack,collapse="\n"), envir=tryenv)
      }), silent=silent)
    if(inherits(out, "try-error")) out[2] <- tryenv$stackmsg
    out
    }
    
    lower <- function(a) a+10
    upper <- function(b) {plot(b, main=b) ; lower(b) }
    
    d <- tryStack(upper(4))
    d <- tryStack(upper("4"))
    cat(d[2])
    

    我的答案中的更多信息: https://stackoverflow.com/a/40899766/1587132

    【讨论】:

    • 虽然这在理论上可以回答这个问题,it would be preferable 在此处包含此特定问题的答案的基本部分,并提供链接以供参考。这也适用于您最近添加的其他答案。
    【解决方案3】:

    函数tools:::.try_quietly做了类似的事情:

    f <- function() {
      g <- function() stop("test traceback")
      g()
    }
    
    tools:::.try_quietly(f()) 
    
    Error: test traceback
    Call sequence:
    3: stop("test traceback")
    2: g()
    1: f()
    

    但是,错误和警告使用sink() 打印到outConn - 这意味着您不能直接将结果分配给对象。要解决此问题,您可能必须更改代码以使用 print() 而不是 sink未尝试)。

    【讨论】:

    • 我也找到了这个,但是它有很多令人讨厌的副作用,并且与tryCatch等不兼容。
    猜你喜欢
    • 1970-01-01
    • 2012-01-12
    • 1970-01-01
    • 2017-08-31
    • 2020-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多