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

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

问题描述

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

我正在尝试捕获错误以记录它们并从错误中优雅地恢复,但我无法获得堆栈跟踪 (traceback) 来记录 R 的代码文件名和行号导致错误的命令.一个(愚蠢的)可重现的例子:

f <- function() {1 + variable.not.found # 愚蠢的错误}tryCatch( f(), error=function(e) {# 在这里我会记录错误消息和堆栈跟踪(回溯)print(e) # 报错信息没问题traceback() # 堆栈跟踪不起作用# 在这里,我将处理错误并恢复...})

运行上面的代码产生这个输出:

<块引用>

f() 中的简单错误:未找到对象variable.not.found"

没有可用的回溯

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

<块引用>

通过 try 或 tryCatch 捕获的错误不会生成回溯,所以打印的是最后一个的调用序列未捕获的错误,不一定是最后一个错误.

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

我该怎么办

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

非常感谢!

解决方案

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

需要解决的主要问题

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

  2. tryCatch 会在捕获时中止执行通过为 warning 条件传递处理函数来发出警告.如果您只想记录警告,则无法正常继续执行.

  3. dump.frames 编写堆栈跟踪的评估环境(帧)以允许事后调试(= 检查每个函数调用中可见的变量值)但 dump.frames如果您设置参数 to.file = TRUE,忘记"也保存工作区.因此可能会丢失重要的对象.

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

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

解决方案概念

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

    莉>

  2. tryCatch 环绕 withCallingHandlers 以根据需要捕获和处理错误.

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

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

  5. R 会在您设置 options(keep.source = TRUE) 时跟踪源代码引用.您可以将此选项添加到您的 .Rprofile 文件中,或使用设置此选项的启动 R 脚本,然后source您的实际 R 脚本.

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

  7. 要从堆栈跟踪中过滤掉 R 内部函数调用,您可以删除所有没有源代码行引用的调用.

实施

代码模板

您应该使用以下代码片段,而不是使用 tryCatch:

library(futile.logger)试着抓(withCallingHandlers(<表达式>,错误 = 函数(e){call.stack <- sys.calls() # 就像withCallingHandlers"中的回溯转储.frames()save.image(file = "last.dump.rda")flog.error(paste(e$message, limitedLabels(call.stack), sep = "
"))}警告 = <类似于上面的错误>}error = <捕捉错误并像往常一样恢复># 警告 = <...># 永远不要在这里这样做,因为它会像错误一样停止正常执行!finally = <您的清理代码放在这里>}

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

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

用法:

library(tryCatchLog) # 或 source("R/tryCatchLog.R")tryCatchLog(<表达式>,错误 = 函数(e){<你的错误处理程序>})

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

https://github.com/aryoda/tryCatchLog

你也可以sourcetryCatchLog 函数,而不是使用完整的包.

示例(演示)

查看提供大量评论的演示文件解释它是如何工作的.

参考文献

其他 tryCatch 替代品

其他有用的链接

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

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

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

如何继续运行R 中的 withCallingHandlers 抛出错误

你能让 R 打印更详细的错误信息吗?

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

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

options(error=dump.frames) vs. options(error=utils::恢复)

在 R 中调试的一般建议

在 R 中使用 tryCatch 抑制警告

R 记录脚本的显示名称

关于srcrefs"属性的背景信息 (Duncan Murdoch)

获取 R 中 tryCatch 错误的堆栈跟踪

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

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:

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

No traceback available

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

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.

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

How can I

  • handle errors and
  • log the stack trace (traceback) for further examination
  • [optionally] without using undocumented or hidden R internal functions that are not guaranteed to work in the future?

THX a lot!

解决方案

Sorry for the long answer but I wanted to summarize all knowledge and references in one answer!

Main issues to be solved

  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.

  2. 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.

  3. 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.

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

  5. Enrich the stack trace with the source code lines.

Solution concept

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

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

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

  4. 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.

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

  6. 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.

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

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

Implementation

Code template

Instead of using tryCatch you should use this code snippet:

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 = "
"))
    }
    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>
}

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.

Usage:

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

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

You can find the free source code at github:

https://github.com/aryoda/tryCatchLog

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

Example (demo)

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

References

Other tryCatch replacements

Other helpful links

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

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