use*_*473 19 error-handling r package
我有时会加载多个导出同名函数的包。比如Hmisc和dplyr都有一个summarize函数,我有时会同时加载两个包。然后我打电话summarize,认为我在打电话dplyr::summarize时我真的在打电话Hmisc::summarize。发生这种情况时,我会收到如下错误消息:
Error in summarize(., mean = mean(instRating)) :
argument "by" is missing, with no default
Run Code Online (Sandbox Code Playgroud)
该消息最初难以理解,因为我的代码不包含任何错误。我花了一分钟才意识到我调用了错误包中的函数。如果第一行包含相关包的名称,错误消息会更容易理解:
Error in Hmisc::summarize(., mean = mean(instRating)) :
Run Code Online (Sandbox Code Playgroud)
有没有办法强制 R 在这些错误消息中显示包名称?
我知道我可以通过输入dplyr::summarize或更改加载包的顺序来解决这个问题。但我的兴趣在于向 R 的错误消息添加细节。
mgw*_*mgw 18
从基本选项的文档中error:
'error':控制非灾难性错误的处理的函数或表达式,例如由 'stop' 以及信号和内部检测到的错误生成的错误。如果选项是一个函数,则对该函数的调用(不带参数)将作为表达式生成。默认情况下,该选项未设置:请参阅“停止”以了解这种情况下的行为。'dump.frames' 和 'recover' 函数提供了允许事后调试的替代方法。请注意,这些需要在诸如“.Rprofile”之类的启动文件中指定为例如“options(error = utils::recover)”。
因此,应该可以定义一个函数,该函数返回抛出错误的函数所在的包的名称。例如:
library(dplyr)
library(Hmisc)
data(mtcars)
print_package <- function() {
calls <- sys.calls()
call <- calls[[length(calls) - 1]]
fun.name <- as.character(call)[1]
pkg.name <- sub("package:", "", getAnywhere(fun.name)$where[1], fixed = TRUE)
message (paste0("In ", pkg.name))
}
options(error = print_package)
summarize(mtcars$mpg)
Run Code Online (Sandbox Code Playgroud)
返回:
Error in summarize(mtcars$mpg) :
argument "by" is missing, with no default
In Hmisc
Run Code Online (Sandbox Code Playgroud)
rlang::trace_back)事实证明,有一种更简洁的方法可以做到这一点(归功于 Hadley Wickham 和他的“高级 R,第二版”):
library(dplyr)
library(Hmisc)
data(mtcars)
print_trace_back <- function() {
print(rlang::trace_back(bottom = sys.frame(-1)))
}
options(error = print_trace_back)
Run Code Online (Sandbox Code Playgroud)
似乎可以优雅地处理错误:
> summarize(mtcars$mpg)
Error in summarize(mtcars$mpg) :
argument "by" is missing, with no default
?
1. ??Hmisc::summarize(mtcars$mpg)
>
> Hmisc::summarize(mtcars$mpg)
Error in Hmisc::summarize(mtcars$mpg) :
argument "by" is missing, with no default
?
1. ??Hmisc::summarize(mtcars$mpg)
>
> summarize(mtcars$mpg, as.character(mtcars$apa), mean)
Error in tapply(X, INDEX, FUN, ..., simplify = simplify) :
arguments must have same length
?
1. ??Hmisc::summarize(mtcars$mpg, as.character(mtcars$apa), mean)
2. ??Hmisc::mApply(X, byc, FUN, ..., keepmatrix = nc > 1)
3. ??base::tapply(X, INDEX, FUN, ..., simplify = simplify)
4. ??base::stop("arguments must have same length")
>
> (function() stop("Error"))()
Error in (function() stop("Error"))() : Error
?
1. ??(function() stop("Error"))()
2. ??base::stop("Error")
Run Code Online (Sandbox Code Playgroud)