如果通过RScript调用tryCatch不会捕获错误

dig*_*All 14 r try-catch

我在R面临一个奇怪的问题.

请考虑以下代码(实际代码的真正简化版本,但仍然存在问题):

library(timeSeries)

tryCatch(
{
  specificWeekDay <- 2

  currTs <- timeSeries(c(1,2),c('2012-01-01','2012-01-02'),
                       format='%Y-%m-%d',units='A')
  # just 2 dates out of range
  start <- time(currTs)[2]+100*24*3600
  end <- time(currTs)[2]+110*24*3600

  # this line returns an empty timeSeries
  currTs <- window(currTs,start=start,end=end)

  message("Up to now, everything is OK")

  # this is the line with the uncatchable error
  currTs[!(as.POSIXlt(time(currTs))$wday %in% specificWeekDay),] <- NA

  message("I'm after the bugged line !")

},error=function(e){message(e)})

message("End")
Run Code Online (Sandbox Code Playgroud)

当我在RGui中运行该代码时,我正确地得到以下输出:

到目前为止,
在为函数'[< - '选择方法时评估参数'i'时一切正常错误:as.POSIXlt.numeric(time(currTs))中的错误:必须提供'origin'
结束

相反,当我使用以下行通过RScript(在Windows中)运行它时:

RScript.exe --vanilla "myscript.R"
Run Code Online (Sandbox Code Playgroud)

我得到这个输出:

到目前为止,一切正常
执行中断

似乎RScript崩溃了......

有什么想法吗?
这是一个timeSeries包错误,还是我做错了什么?
如果是后者,那么确保捕获所有错误的正确方法是什么?

提前致谢.


编辑:

这是一个较小的示例,再现了不使用timeSeries包的问题.要测试它,只需按上述方法运行它:

library(methods)
# define a generic function
setGeneric("foo", 
           function(x, ...){standardGeneric("foo")})
# set a method for the generic function
setMethod("foo", signature("character"),
          function(x) {x})
tryCatch(
{
  foo("abc")
  foo(notExisting)
},error=function(e)print(e))
Run Code Online (Sandbox Code Playgroud)

这似乎与泛型方法调度有关; 当一个方法的参数导致错误时,调度程序无法找到该方法的签名,并且后果地提出了一个异常,该tryCatch函数在运行RScript时似乎无法处理.
奇怪的是,它不会发生在例如print(notExisting); 在这种情况下,正确处理异常.

有关原因以及如何捕获此类错误的任何想法?

注意:
我在Windows 7上使用R-2.14.2

Luk*_*ney 17

问题在于实现S4方法调度的内部C代码尝试捕获和处理一些错误以及如何在此方法中处理非交互式案例.应该在R-devel和R-patched中进行解决方案.

解决方案现在致力于R-devel和R-patched.

  • 欢迎来到Stack Overflow!感谢您在R核心团队中的所有工作. (5认同)
  • 谢谢卢克!很高兴见到你. (3认同)

Rei*_*son 6

关于tryCatch()[OP已经知道并使用但我没注意到的]的信息

我认为你缺少你tryCatch()不是有什么特别的,出现错误,因此你在正常的方式引发错误.在交互式使用中,错误以通常的方式抛出和处理,但是在非交互式会话(a la Rscript)中运行的脚本内的错误将中止正在运行的脚本.

tryCatch()是一个复杂的函数,它允许捕获和处理R中的各种事件,而不仅仅是错误.但是,默认情况下,它被设置为模仿标准R错误处理过程; 基本上允许R抛出并报告错误.如果你想让R做除基本行为以外的任何事情,那么你需要为错误添加一个特定的处理程序:

> e <- simpleError("test error")
> tryCatch(foo, error = function(e) e,
+          finally = writeLines("There was a problem!"))
There was a problem!
<simpleError in doTryCatch(return(expr), name, parentenv, handler): object 'foo'
not found>
Run Code Online (Sandbox Code Playgroud)

我建议你仔细阅读?tryCatch,以便更好地了解它的作用.

另一种方法是使用try().要修改你的脚本,我会这样做:

# this is the line with the uncatchable error
tried <- try(currTs[!(as.POSIXlt(time(currTs))$wday %in% specificWeekDay),] <- NA,
             silent = TRUE)
if(inherits(tried, "try-error")) {
    writeLines("There was an error!")
} else {
    writeLines("Everything worked fine!")
}
Run Code Online (Sandbox Code Playgroud)

关键是保存返回的对象,try()以便您可以测试类,并以try()静默方式运行.考虑一下差异:

> bar <- try(foo)
Error in try(foo) : object 'foo' not found
> bar <- try(foo, silent = TRUE)
> class(bar)
[1] "try-error"
Run Code Online (Sandbox Code Playgroud)

请注意,在上面的第一个调用中,错误被捕获报告为消息.在第二个,没有报道.在这两种情况下"try-error"都返回类的对象.

在内部,try()编写为单个调用,tryCatch()为错误处理程序设置自定义函数,该错误处理程序将错误报告为消息并设置返回的对象.您可能希望将R代码try()作为另一个使用示例进行研究tryCatch().

  • 谢谢你的答案,但我不认为我完全得到你.我的意思是,我已经为错误设置了一个处理程序(即错误=函数(e){message(e)}),因此,当遇到错误时,它应该调用此函数并停止对表达式的求值,对吧?(实际上它确实如此,不包括这个特例).也许我遇到的异常不会从错误类继承? (2认同)