我想在 R 中编写一个自定义错误函数,使用更一致的错误消息格式。在基础 R 中,错误的格式是这样的:如果错误消息超出控制台宽度,则将其放在新行上,并将其缩进两个空格:
abort <- function(msg) stop(msg)
> abort("This is a very very very very long error message")
# Error in abort("This is a very very very very long error message") :
# This is a very very very very long error message
如果它不超过控制台宽度,则直接将其放在调用后面:
> abort("Short message")
# Error in abort("Short message") : Short message
在我的自定义错误函数中,我打算通过始终在新行上开始显示错误消息来保持格式更加一致(类似于cli
包错误格式):
abort <- function(msg) stop("\n", msg)
但是,当将此函数与非常长的错误消息(或长调用)一起使用时,基本 R 错误格式会在错误输出中添加新行,从而添加不需要的空格。
> abort("This is a very very very very very very very very long error message")
# Error in abort("This is a very very very very very very very very long error message") :
#
# This is a very very very very very very very very long error message
有没有什么方法可以控制这种行为,通过抑制它或者通过找出它发生的时间并手动解决它?
使用 可以很容易地暂时停止打印错误消息
options(show.error.messages = FALSE)
,然后将您想要的任何消息打印到控制台。此后,您可以使用简单的方法抛出错误stop(msg)
以停止执行,并且只会显示您自己的定制消息。这种方法的致命问题是,程序停止后,您还没有重新打开用户的错误打印,这是一个大问题。您不能
abort
在调用后简单地重置内部的用户选项stop()
,因为程序已经停止,而您的选项重置代码将不会执行。这就是 R 基础函数的作用
on.exit()
所在。这个方便的函数允许您提供一个任意的代码块,在函数退出后运行,即使函数因未处理的错误而退出。因此,只要我们在程序之前注册指令,我们就可以告诉on.exit
用户在退出函数时重置用户的选项。abort
on.exit
stop()
该机制的本质是如何
rlang
通过函数生成具有定制格式的错误消息rlang:::signal_abort
。我们还想检查调用堆栈,以便我们可以告诉用户在哪里
abort
遇到了,因此最小的实现可能是这样的:测试,我们得到:
如果我们
abort
在函数内部遇到这种情况,我们可以看到执行已暂停,并且我们会获得有关导致触发的调用的一些信息abort
:@AllanCamerons 的回答已经非常优雅地回答了我的问题。但是,有一个问题一直困扰着我:该函数同时发出消息和错误信号。在研究了的源代码后,我发现和
rlang::signal_abort()
的混合主要反映了的行为:signalCondition()
cat()
rlang::abort()
我认为这样做的目的是:
signalCondition(cnd)
是发出错误情况信号并指定“官方”错误消息(作为捕获的条件处理程序)但不会中止执行的地方。cat(..., file = stderr())
打印到 stderr 但不发出消息。stop("")
中止执行,但既不发出另一个错误信号(因为这已经在之前完成了),也不打印错误消息(因为它被抑制了)。为什么这很有用: