我在服务器上运行的R中有许多无人值守的批处理作业,运行后我必须分析作业失败。

我试图捕获错误以将其记录并从错误中恢复,但是我无法获取堆栈跟踪(traceback)来记录导致错误的R命令的代码文件名和行号。 (愚蠢的)可复制示例:

f <- function() {
  1 + variable.not.found    # stupid error
}

tryCatch( f(), error=function(e) {
  # Here I would log the error message and stack trace (traceback)
  print(e)            # error message is no problem
  traceback()         # stack trace does NOT work
  # Here I would handle the error and recover...
})

运行上面的代码将产生以下输出:



跟踪不可用,其原因已在R帮助(?traceback)中记录:



换句话说:使用tryCatch捕获错误确实会杀死堆栈跟踪!

我怎么能够
  • 处理错误
  • 记录堆栈跟踪(回溯)以进一步检查
  • [可选地]是否使用了未保证将来无法使用的未记录或隐藏的R内部函数?

  • 多谢!

    最佳答案

    很抱歉,回答很长,但我想在一个答案中总结所有知识和引用!

    要解决的主要问题

  • tryCatch将调用堆栈“展开”到tryCatch调用,以便tracebacksys.calls不再包含完整的堆栈跟踪,以标识导致错误或警告的源代码行。
  • 通过传递tryCatch条件的处理程序函数
  • warning aborts the execution if you catch a warning。如果只想记录警告,则无法照常继续执行。
  • dump.frames写入堆栈跟踪的评估环境(框架),以允许事后调试(=检查每个函数调用中可见的变量值),但是 dump.frames "forgets" to save the workspace too if you set the parameter to.file = TRUE 。因此,重要的对象可能会丢失。
  • 因为R不支持开箱即用的ogt_rli,所以找到一个简单的日志记录框架
  • 用源代码行丰富堆栈跟踪。

  • 解决方案概念
  • 使用withCallingHandlers而不是tryCatch获取指向引发错误或警告的源代码行的完整堆栈跟踪。
  • 仅在withCallingHandlers(而不是tryCatch)内捕获警告,因为它仅调用处理程序函数,但不会更改程序流。
  • withCallingHandlers包围tryCatch,以根据需要捕获和处理错误。
  • dump.frames与参数to.file = FALSE一起使用,将转储写入名为last.dump的全局变量中,并通过调用save.image将其与全局环境一起保存到文件中。
  • 使用日志记录框架,例如。 G。包futile.logger
  • 设置options(keep.source = TRUE)时,
  • R会跟踪源代码引用。您可以将此选项添加到.Rprofile文件中,也可以使用设置该选项的启动R脚本,然后使用source您的实际R脚本。
  • 要使用跟踪的源代码行丰富堆栈跟踪,可以使用未公开说明(但广泛使用)的limitedLabels函数。
  • 要从堆栈跟踪中筛选出R个内部函数调用,您可以删除所有没有源代码行引用的调用。

  • 实作

    代码模板

    代替使用tryCatch,您应该使用以下代码片段:
    library(futile.logger)
    
    tryCatch(
      withCallingHandlers(<expression>,
        error = function(e) {
          call.stack <- sys.calls() # is like a traceback within "withCallingHandlers"
          dump.frames()
          save.image(file = "last.dump.rda")
          flog.error(paste(e$message, limitedLabels(call.stack), sep = "\n"))
        }
        warning = <similar to error above>
      }
      error = <catch errors and recover as you would do it normally>
      # warning = <...> # never do this here since it stops the normal execution like an error!
      finally = <your clean-up code goes here>
    }
    

    通过包(tryCatchLog)可重用的实现

    我已经用上述所有概念实现了一个简单的程序包。
    它使用tryCatchLog包提供功能futile.logger

    用法:
    library(tryCatchLog)  # or source("R/tryCatchLog.R")
    
    tryCatchLog(<expression>,
                error = function(e) {
                  <your error handler>
                })
    

    您可以在github上找到免费的源代码:

    https://github.com/aryoda/tryCatchLog

    您也可以source tryCatchLog function,而不使用完整的软件包。

    示例(演示)

    请参阅demo file,其中提供了很多注释以解释其工作方式。

    引用文献

    其他tryCatch替换
  • 记录警告和错误,并具有在try catch中执行多次尝试(重试)的功能。 G。用于访问不可靠的网络驱动器:

    Handling errors before warnings in tryCatch
  • withJavaLogging函数不依赖于其他软件包,该函数还使用limitedLabels丰富了对调用堆栈的源代码引用:

    Printing stack trace and continuing after error occurs in R

  • 其他有用的链接

    http://adv-r.had.co.nz/Exceptions-Debugging.html

    A Warning About warning() - avoid R's warning feature

    In R, why does withCallingHandlers still stops execution?

    How to continue function when error is thrown in withCallingHandlers in R

    Can you make R print more detailed error messages?

    How can I access the name of the function generating an error or warning?

    How do I save warnings and errors as output from a function?

    options(error=dump.frames) vs. options(error=utils::recover)

    General suggestions for debugging in R

    Suppress warnings using tryCatch in R

    R Logging display name of the script

    Background information about the "srcrefs" attribute (Duncan Murdoch)

    get stack trace on tryCatch'ed error in R

    关于r - R : Catch errors and continue execution after logging the stacktrace (no traceback available with tryCatch),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/62900655/

    10-12 19:42