14

我在 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")

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

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

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

RScript.exe --vanilla "myscript.R"

我得到这个输出:

截至目前,一切正常
执行中断

好像 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))

似乎与通用方法调度有关;当方法的参数导致错误时,调度程序无法找到该方法的签名,并随之引发tryCatch函数在通过 RScript 运行时似乎无法处理的异常。
奇怪的是,它不会发生,例如print(notExisting); 在这种情况下,异常会得到正确处理。

关于原因以及如何捕捉这种错误的任何想法?

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

4

2 回答 2

17

问题在于实现 S4 方法分派的内部 C 代码尝试捕获和处理一些错误的方式以及在这种方法中如何处理非交互式情况。应尽快在 R-devel 和 R-patched 中制定解决方法。

解决方法现在致力于 R-devel 和 R-patched。

于 2012-07-11T16:46:05.723 回答
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>

我建议您?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!")
}

关键是保存返回的对象,try()以便您可以测试该类,并try()进行静默操作。考虑差异:

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

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

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

于 2012-07-09T11:19:48.953 回答