是否可以在 R 中处理简单消息?如果是,如何?

Is it possible to handle simple messages in R? If yes, how?

处理警告或错误可以使用

result = tryCatch({
    expr
}, warning = function(w) {
    warning-handler-code
}, error = function(e) {
    error-handler-code
}, finally = {
    cleanup-code
}

但是如果 expr 给出 messagesimpleMessage,我怎样才能得到它?有没有类似的东西?:

message = function(m) {message-handler-code}

或者另一个允许我捕获消息的函数?

谢谢!

是的,您可以像使用 warningerror 一样使用 message = :

result = tryCatch({
    message("Hello world")
    1 + 1
}, message = function(m) {m}
)

result
#> <simpleMessage in message("Hello world"): Hello world
>

不过,您更有可能希望分别捕获结果和消息:

result <- withCallingHandlers({
    message("Hello world")
    1 + 1
}, message = function(m) {
    lastMessage <<- m
    invokeRestart("muffleMessage")
})

result
#> [1] 2

if(exists("lastMessage")) message(lastMessage)
#> Hello world

tryCatch 是处理条件最常用的解决方案。

但是,tryCatch中止执行和returns处理程序的值,而不是恢复代码的执行。这可能并不总是您想要的;有时您想处理一个条件并继续。

R 由于其 incredibly powerful condition system.

允许这样做

例如,您可以选择静音所有消息:

suppressMessages(expr)

这里的好处是 suppressMessages 并不神奇 — 它是一个普通的旧 R 函数,您可以自己编写它(但您需要了解条件系统及其价格多功能性在于它相当复杂)。

为了说明这一点,这里有另一种处理消息的方法——使用 withCallingHandlers——它会抑制消息,继续执行调用它的代码,但同时将消息记录在列表中:

messages = list()

withCallingHandlers({
    message('Hello world')
    1 + 1
}, message = function (msg) {
    messages <<- c(messages, msg)
    tryInvokeRestart('muffleMessage')
})

tryInvokeRestart('muffleMessage')suppressMessages 的工作方式相同。唯一的区别是我们添加了代码来存储消息。

作为最后一步,上面的内容甚至可以包含在一个函数中:

with_logging = function (expr) {
    messages = list()

    log_message = function (msg) {
        messages <<- c(messages, conditionMessage(msg))
        tryInvokeRestart('muffleMessage')
    }

    result = withCallingHandlers(expr, message = log_message)
    list(result = result, messages = messages)
}

并使用它:

with_logging({
    message('this is a test')
    1 + 1
})
$result
[1] 2

$messages
$messages[[1]]
[1] "this is a test\n"