【问题标题】:How to get the last error如何获取最后一个错误
【发布时间】:2016-05-01 11:18:07
【问题描述】:

我可以使用.Last.value得到最后计算的值

2 + 2
## [1] 4
.Last.value
## [1] 4

我可以使用last.warning 访问最新的警告。

warning("!!!")
## Warning message:
## !!! 
last.warning
## $`!!!`
##  NULL

我可以使用geterrmessage()获取最新错误消息的文本

stop("!!!")
## Error: !!!
geterrmessage()
## [1] "Error: !!!\n"

如果我事先知道可能会引发错误,我可以使用tryCatch 返回错误对象。

tryCatch(stop("!!!"), error = identity)
## <simpleError in doTryCatch(return(expr), name, parentenv, handler): !!!>

在抛出最后一个错误后,如何将其检索为对象?

例如,如果我输入

stop("!!!")

然后我希望能够输入getlasterror() 或类似的内容并检索simpleError 对象。

【问题讨论】:

  • 我想知道这是不是traceback() 的意思?
  • @DavidArenburg 好主意,但似乎traceback() 和底层baseenv()$.Traceback 仅将错误消息的调用堆栈存储为字符串对。所以我只得到"stop(\"!!!\")" 而不是错误对象。
  • 那么你想要的输出是什么?
  • 我想要 simpleError 对象,就像您通过运行 tryCatch(stop("!!!"), error = identity) 得到的一样,除了我想在已经抛出错误之后检索它。
  • 嗯......也许像tryCatch(eval(parse(text = traceback())), error = identity)这样的黑客?

标签: r error-handling


【解决方案1】:

现代方式

如果您是代码的作者,解决此问题的现代方法是使用 rlang 包。您使用abort() 抛出错误,然后使用last_error() 检索最后一个错误。

library(rlang)
f <- function() {
  abort("@@@")
}
f()
## Error: @@@
last_error()
## <error>
## message: @@@
## class:   `rlang_error`
## backtrace:
##  ─base::withCallingHandlers(...)
##  ─global::f()
## Call `summary(rlang::last_error())` to see the full backtrace
g <- function() {
  msg <- "###"
  abort(msg)
}
g()
## Error: ###
last_error()
## <error>
## message: ###
## class:   `rlang_error`
## backtrace:
##  ─base::withCallingHandlers(...)
##  ─global::g()
## Call `summary(rlang::last_error())` to see the full backtrace
h <- function() {
  err_fn <- abort
  err_fn("$$$")
}
h()
## Error: $$$
last_error()
## <error>
## message: $$$
## class:   `rlang_error`
## backtrace:
##  ─base::withCallingHandlers(...)
##  ─global::h()
## Call `summary(rlang::last_error())` to see the full backtrace

这个限制是它不适用于stop()产生的错误。


原来的答案

根据 David Arenburg 的评论,您可以将 tryCatch() 与回溯结合使用。

get_last_error <- function()
{
  tr <- .traceback()
  if(length(tr) == 0)
  {
    return(NULL)
  }
  tryCatch(eval(parse(text = tr[[1]])), error = identity)
}

例子:

# before an error is thrown
get_last_error()
## NULL

# after an error at the top level
stop("!!!")
## Error: !!!
get_last_error()
## <simpleError in eval(expr, envir, enclos): !!!>

# after an error inside a function
f <- function() stop("@@@")
f()
## Error in f() : @@@
get_last_error()
## <simpleError in eval(expr, envir, enclos): @@@>

限制:

当您重新评估错误代码时,所有变量都需要可用。所以下面的例子不起作用,例如:

g <- function()
{
  msg <- "###"
  stop(msg)
}

g()
## Error in g() : ###
get_last_error()
## <simpleError in stop(msg): object 'msg' not found>

h <- function()
{
  err_fn <- stop
  err_fn("$$$")
}

h()
## Error in h() : $$$
get_last_error()
## <simpleError in eval(expr, envir, enclos): could not find function "err_fn">

通过设置options(error = dump.frames),将出错时的调用堆栈存储在全局环境中名为last.dump的变量中。环境last.dump[length(last.dump)] 有时包含错误对象,有时包含会导致错误的参数。

debugger(last.dump) 允许对堆栈进行交互式事后探索,作为拥有错误对象的替代方法。

【讨论】:

  • .traceback() 是错字吗?
  • 不是错字! .tracebacktraceback 类似,只是它不强制打印堆栈。
  • 运行时出现“get_last_error() 中的错误:找不到函数“.traceback””...
  • 好地方。这似乎是一个新功能,目前仅在 R-devel 中。它在 R-3.2.5 中不存在。
猜你喜欢
  • 2010-10-20
  • 2019-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多