本文介绍了从 R 代码调用中断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个通用函数来捕获包中包含的所有异常 logR::tryCatch2 定义为:

I have a generic function to catch all exceptions included in my package logR::tryCatch2 defined as:

tryCatch2 <- function(expr){
    V=E=W=M=I=NULL
    e.handler = function(e){
        E <<- e
        NULL
    }
    w.handler = function(w){
        W <<- c(W, list(w))
        invokeRestart("muffleWarning")
    }
    m.handler = function(m){
        attributes(m$call) <- NULL
        M <<- c(M, list(m))
    }
    i.handler = function(i){
        I <<- i
        NULL
    }
    V = suppressMessages(withCallingHandlers(
        tryCatch(expr, error = e.handler, interrupt = i.handler),
        warning = w.handler,
        message = m.handler
    ))
    list(value=V, error=E, warning=W, message=M, interrupt=I)
}

正如您在最后一行中看到的那样,它返回一个或多或少是自我描述的列表.
它通过简单的 !is.nulltryCatch2 调用后延迟的异常做出真正的反应:

As you can see in the last line it returns a list which is more or less self describing.
It makes the real reaction to the exceptions delayed after the tryCatch2 call by simple !is.null:

f = function(){ warning("warn1"); warning("warn2"); stop("err") }
r = tryCatch2(f())
if(!is.null(r$error)) cat("Error detected\n")
# Error detected
if(!is.null(r$warning)) cat("Warning detected, count", length(r$warning), "\n")
# Warning detected, count 2 

它按预期工作,我可以用我自己的代码做出反应.但在某些情况下,我不想停止被捕获的 interrupt 进程.目前看来我需要向 tryCatch2 添加额外的参数来控制是否应该捕获中断.所以这个问题询问了一些我可以通过以下方式使用的 invokeInterrupt 函数:

It works as expected, I can react with my own code. But in some cases I would like to not stop the interrupt process which is caught too. At the moment it seems I would need to add additional parameter to tryCatch2 which would control if interrupts should be catch or not. So the question asks about some invokeInterrupt function which I could use in the following way:

g = function(){ Sys.sleep(60); f() }
r = tryCatch2(g())
# interrupt by pressing ctrl+c / stop while function is running!
if(!is.null(r$interrupt)) cat("HERE I would like to invoke interrupt\n")
# HERE I would like to invoke interrupt

我认为如果 R 能够捕获一个,它也应该能够调用一个.
如何实现 invokeInterrupt 功能?

I think if R is able to catch one it should be also able to invoke one.
How can I achieve invokeInterrupt functionality?

推荐答案

Late answer 但我发现 rlang::interrupt 可以抛出用户中断":

Late answer but I have found that rlang::interrupt can throw "user interrupts":

interrupt() 允许 R 代码模拟用 Ctrl-C 发出信号的那种用户中断.目前无法创建自定义中断条件对象.

来源:?rlang::interrupt

它在内部调用 R API 函数 Rf_onintr,它是函数的别名 onintr.

Internally it calls the R API function Rf_onintr which is an alias for the function onintr.

基本上,中断只是"这些类的特殊条件:interruptcondition(参见 R 源代码).

Basically an interrupt is "just" a special condition with these classes:interrupt and condition (see the R source code).

如果您只是想模拟一个中断来测试 tryCatching(无需中断正在运行的 R 语句),那么通过 signalCondition:

If you just want to simulate an interrupt to test tryCatching (without the need to interrupt a running R statement) it suffice to throw a condition with these classes via signalCondition:

interrupt_condition <- function() {
  structure(list(), class = c("interrupt", "condition"))
}

tryCatch(signalCondition(interrupt_condition()),
                         interrupt = function(x) print("interrupt detected"))
# [1] "interrupt detected"

这篇关于从 R 代码调用中断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-21 12:26