R:在记录堆栈跟踪后捕获错误并继续执行(tryCatch没有可用的回溯) [英] R: Catch errors and continue execution after logging the stacktrace (no traceback available with tryCatch)

查看:105
本文介绍了R:在记录堆栈跟踪后捕获错误并继续执行(tryCatch没有可用的回溯)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have many unattended batch jobs in R running on a server and I have to analyse job failures after they have run.

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

I am trying to catch errors to log them and recover from the error gracefully but I am not able to get a stack trace (traceback) to log the code file name and line number of the R command that caused the error. A (stupid) reproducible example:

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...
})

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

Running the code above produces this output:

f()中的simpleError:找不到对象'variable.not.found'

simpleError in f(): object 'variable.not.found' not found

没有可用的追溯

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

The traceback is not available and the reason is documented in the R help (?traceback):

通过try或tryCatch捕获的错误不会生成 追溯,因此打印的是最后一个的调用顺序 未捕获的错误,不一定是最后一个错误.

Errors which are caught via try or tryCatch do not generate a traceback, so what is printed is the call sequence for the last uncaught error, and not necessarily for the last error.

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

In other words: Catching an error with tryCatch does kill the stack trace!

我怎么

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

很多钱!

推荐答案

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

  1. tryCatch将调用堆栈展开"到tryCatch调用,以便tracebacksys.calls不再包含完整的堆栈跟踪以标识导致错误或警告的源代码行.

  1. tryCatch "unrolls" the call stack to the tryCatch call so that traceback and sys.calls do no longer contain the full stack trace to identify the source code line that causes an error or warning.

tryCatch如果收到警告,则中止执行通过传递warning条件的处理函数.如果只想记录警告,则无法照常继续执行.

tryCatch aborts the execution if you catch a warning by passing a handler function for the warning condition. If you just want to log a warning you cannot continue the execution as normal.

dump.frames编写堆栈跟踪的评估环境(框架)以允许事后调试(=检查每个函数调用中可见的变量值),但to.file = TRUE .因此重要的对象可能会丢失.

dump.frames writes the evaluation environments (frames) of the stack trace to allow post-mortem debugging (= examining the variable values visible within each function call) but dump.frames "forgets" to save the workspace too if you set the parameter to.file = TRUE. Therefore important objects may be missing.

找到一个简单的日志记录框架,因为R不支持开箱即用的日志记录

Find a simple logging framework since R does not support decent logging out of the box

使用源代码行丰富堆栈跟踪.

Enrich the stack trace with the source code lines.

解决方案概念

  1. 使用withCallingHandlers而不是tryCatch获取指向引发错误或警告的源代码行的完整堆栈跟踪.

  1. Use withCallingHandlers instead of tryCatch to get a full stack trace pointing to the source code line that throwed an error or warning.

仅在withCallingHandlers内捕获警告(在tryCatch中不捕获),因为它仅调用处理程序函数,但不会更改程序流.

Catch warnings only within withCallingHandlers (not in tryCatch) since it just calls the handler functions but does not change the program flow.

tryCatch包围withCallingHandlers,以根据需要捕获和处理错误.

Surround withCallingHandlers with tryCatch to catch and handle errors as wanted.

使用dump.frames和参数to.file = FALSE将转储写入名为last.dump的全局变量,并通过调用save.image将其与全局环境一起保存到文件中.

Use dump.frames with the parameter to.file = FALSE to write the dump into global variable named last.dump and save it into a file together with the global environment by calling save.image.

使用日志记录框架,例如G.包futile.logger.

Use a logging framework, e. g. the package futile.logger.

R会跟踪源代码引用.您可以将此选项添加到.Rprofile文件中,也可以使用设置该选项的启动R脚本,然后使用source您的实际R脚本.

R does track source code references when you set options(keep.source = TRUE). You can add this option to your .Rprofile file or use a startup R script that sets this option and source your actual R script then.

要使用跟踪的源代码行丰富堆栈跟踪,可以使用未记录(但广泛使用)的功能limitedLabels.

To enrich the stack trace with the tracked source code lines you can use the undocumented (but widely used) function limitedLabels.

要从堆栈跟踪中筛选出R个内部函数调用,可以删除所有没有源代码行引用的调用.

To filter out R internal function calls from stack trace you can remove all calls that have no source code line reference.

实施

代码模板

您应该使用以下代码段,而不是使用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)可重用的实现

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

Reusable implementation via a package (tryCatchLog)

I have implemented a simple package with all the concepts mentioned above. It provides a function tryCatchLog using the futile.logger package.

用法:

library(tryCatchLog)  # or source("R/tryCatchLog.R")

tryCatchLog(<expression>,
            error = function(e) {
              <your error handler>
            })

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

You can find the free source code at github:

https://github.com/aryoda/tryCatchLog

您还可以source tryCatchLog函数而不是使用完整的包装.

You could also source the tryCatchLog function instead of using a full blown package.

请参见演示文件,其中提供了很多注释解释它是如何工作的.

See the demo file that provides a lot of comments to explain how it works.

  • 记录警告和错误,并具有在尝试捕获时执行多次尝试(重试)的功能,例如e. G.访问不可靠的网络驱动器:

  • Logging of warnings and errors with with a feature to perform multiple attempts (retries) at try catch, e. g. for accessing an unreliable network drive:

在tryCatch中的警告之前处理错误

withJavaLogging函数不依赖于其他软件包,这也使用limitedLabels丰富了对调用堆栈的源代码引用:

withJavaLogging function without any dependencies to other packages which also enriches the source code references to the call stack using limitedLabels:

打印堆栈跟踪并在发生错误后继续R

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

关于警告()的警告-避免R的警告功能

在R中,为什么withCallingHandlers仍然停止执行?

如何在何时继续运行R

可以让R打印更详细的错误消息吗? /a>

Can you make R print more detailed error messages?

如何我可以访问产生错误或警告的函数的名称吗?

如何如何将警告和错误保存为函数的输出?

选项(错误= dump.frames)与选项(错误= utils ::恢复)

在R中进行调试的一般建议

在R中使用tryCatch抑制警告

R记录脚本的显示名称

有关"srcrefs"属性的背景信息(邓肯·默多克)

获取有关R中tryCatched错误的堆栈跟踪信息

这篇关于R:在记录堆栈跟踪后捕获错误并继续执行(tryCatch没有可用的回溯)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆