强制 R 始终在错误消息中显示包名称

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)