博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[R]R语言里的异常处理与错误控制
阅读量:5340 次
发布时间:2019-06-15

本文共 5122 字,大约阅读时间需要 17 分钟。

之前一直只是在写小程序脚本工具,几乎不会对异常和错误进行控制和处理。

随着脚本结构和逻辑更复杂,脚本输出结果的准确性验证困难,同时已发布脚本的维护也变得困难。所以也开始考虑引入异常处理和测试工具的事情。

不过好像R语言的异常处理似乎有些辣鸡?查了下资料和try的文档说明,感觉说的并不清楚。

在网上查了一些资料,对R语言异常处理做了比较详细的说明,留档作为参考。至于测试工具的问题,后续还是再考虑下。

文章链接:

原文参考了以下几个网页:

http://stackoverflow.com/questions/14059657/how-to-skip-an-error-in-a-loop

http://stackoverflow.com/questions/8093914/skip-to-next-value-of-loop-upon-error-in-r-trycatch (这个链接里还连接了非常多的关于R语言异常处理)。

============================= 本人的分割线 ===============================

在开始之前,或许应该参考一下其他语言里面的异常处理机制。

先奉上Java方面的参考资料:

 

除了第4点,其他基本无参考意义。因为R已经将比较底层的东西给隐藏起来,异常(运行时异常、编译异常等)方面的资料也缺少(cran文档库也没有很具体的信息)。所以这里只参考第四点,讨论处理异常机制。

R语言处理异常机制:

异常的处理分为抛出异常捕捉异常

抛出异常:当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。

虽然不确定R中是否存在运行时系统这个概念,但是其他地方的描述,应该是跟Java的异常是一致的。

捕捉异常:

 

如果tryCatch中调用的语句产生一个错误,它会执行一个以error为参数的函数,并返回这个函数的值。以error为参数的函数,需要将错误本身作为一个参数(这里称之为e),但是我们可以不对它做任何操作。

当然,我们也可以使用较为简单的try语句。选择哪个基于各自的喜好。

假如你的语句产生一个错误,try会返回一个类型为try-error的对象,并将其信息输出至屏幕(若silent=FALSE)。

 

===== 0524 更 ========

http://stackoverflow.com/questions/8093914/skip-to-next-value-of-loop-upon-error-in-r-trycatch

使用tryCatch需要知道很关键的一点: tryCatch会返回一个对象。见如下代码:

x <- tryCatch(stop("Error"), error = function(e) e)class(x)"simpleError" "error"       "condition"

如果在tryCatch中存在一个error,则这个返回的对象会继承error类。我们可以通过inherit函数来检验类继承。

另: 在tryCatch中的参数 error = function(e) e 是什么意思呢?

这有点难到我了。文档中也没有看到很好的解释。这当中的过程是,这个参数会捕获你在tryCatch中的代码表达式产生的任何error信息。假如捕获到error,它则将返回的值作为tryCatch的值(记住tryCatch会返回一个对象)。文档中将其称为calling handler。在 error = function(e)中的e, 就是你代码表达式中的错误信息。

关于在循环代码中使用next:

程序性编程中认为使用next不太好。所以假如想要在for循环中去掉next,可以考虑:

 

for (i in 1:39487) {  #ERROR HANDLING  possibleError <- tryCatch(      thing(),      error=function(e) e  )  if(!inherits(possibleError, "error")){    #REAL WORK    useful(i); fun(i); good(i);  }}  #end for

 ======= 果然不只是我对tryCatch的文档云里雾里.... ================

参见:

在开始之前,我们先了解下异常处理中的相关函数列表。以下是这方面函数的最精简的列表了:

  •  warning(...) - 生成warnings
  • stop(...) - 生成errors
  • suppressWarnings(expr) - 运行expr表达式, 并忽略任何warnings
  • tryCatch(...) - 运行代码并赋值给异常处理器(exception handlers)

还有其他与异常处理相关的函数,不过以上这些已经足够我们了解R的异常处理了。

R 异常处理与 JAVA中的try-catch-finally机制不同

如果你注意到的话,R在很多问题的处理上和其他大多数语言都不一样。

Java、Python和C以及其他在此维基页面()上提到的语言,都使用语言语句(即关键字)来实现try-catch-finally。但R就特立独行,它使用一个函数来实现....

不过如果你代码写的好的话,tryCatch()函数其实看起来和其他语言的try-catch语法差不多。上代码:

result = tryCatch({    expr}, warning = function(w) {    warning-handler-code}, error = function(e) {    error-handler-code}, finally = {    cleanup-code}

在tryCatch()中,可以处理两种情况:'warnings' 和 'errors'.要理解每一块代码的意义,关键是要清楚代码的运行状态与作用域。以下节选自?tryCatch文档:

If a condition is signaled while evaluating ‘expr’ then [...] control is transferred to the ‘tryCatch’ call that established the handler[...] and the result returned by the handler is returned as the value of the ‘tryCatch’ call. [...] The ‘finally’ expression is then evaluated in the context in which ‘tryCatch’ was called.

'expr'一次执行一行,直到遇到'condition',然后程序执行会完整地转移给handler。

代码能比文字表达更多信息。文末的独立R脚本展现了一个健壮的异常处理系统的各种特性:

  • 在一个函数中产生warnings和errors
  • 在tryCatch()中设置warning和error处理器(handler)
  • 当函数产生warning或error时,提供备选的返回值
  • 修改warning和error信息的内容
  • 抑制warning信息

复制粘贴文末的脚本,使其可执行,并使用以下命令执行:

$ chmod +x tryCatch.Rscript$ ./tryCatch.r 1$ ./tryCatch.r 0$ ./tryCatch.r a$ ./tryCatch.r$ ./tryCatch.r warning$ ./tryCatch.r error$ ./tryCatch.r suppress-warnings

注意当'suppress-warnings'时发生了什么。

以下是一些你需要知道的,关于这个实验脚本的信息:

  1. tryCatch()的使用并不难(一旦你知道如何使用)
  2. condition handler 能访问到warning()和stop()信息
  3. 在传递函数参数之前,准备好合适的类型转换。
  4. 最理想的情况是,tryCatch()的代码表达式只是一个单独的函数。

以下是tryCatch.Rscript范例脚本。Hope You enjoy Error handling.

#!/usr/bin/env Rscript# tryCatch.Rscript -- experiments with tryCatch# Get any argumentsarguments <- commandArgs(trailingOnly=TRUE)a <- arguments[1]# Define a division function that can issue warnings and errorsmyDivide <- function(d, a) {  if (a == 'warning') {    return_value <- 'myDivide warning result'    warning("myDivide warning message")  } else if (a == 'error') {    return_value <- 'myDivide error result'    stop("myDivide error message")  } else {    return_value = d / as.numeric(a)  }  return(return_value)}# Evalute the desired series of expressions inside of tryCatchresult <- tryCatch({  b <- 2  c <- b^2  d <- c+2  if (a == 'suppress-warnings') {    e <- suppressWarnings(myDivide(d,a))  } else {    e <- myDivide(d,a) # 6/a  }  f <- e + 100}, warning = function(war) {  # warning handler picks up where error was generated  print(paste("MY_WARNING:  ",war))  b <- "changing 'b' inside the warning handler has no effect"  e <- myDivide(d,0.1) # =60  f <- e + 100  return(f)}, error = function(err) {  # error handler picks up where error was generated  print(paste("MY_ERROR:  ",err))  b <- "changing 'b' inside the error handler has no effect"  e <- myDivide(d,0.01) # =600  f <- e + 100  return(f)}, finally = {  print(paste("a =",a))  print(paste("b =",b))  print(paste("c =",c))  print(paste("d =",d))  # NOTE:  Finally is evaluated in the context of of the inital  # NOTE:  tryCatch block and 'e' will not exist if a warning  # NOTE:  or error occurred.  #print(paste("e =",e))}) # END tryCatchprint(paste("result =",result))

  

转载于:https://www.cnblogs.com/oDoraemon/p/5511538.html

你可能感兴趣的文章
MSChart的研究
查看>>
C# 索引器
查看>>
MySQLdb & pymsql
查看>>
zju 2744 回文字符 hdu 1544
查看>>
delphi 内嵌汇编例子
查看>>
【luogu P2298 Mzc和男家丁的游戏】 题解
查看>>
前端笔记-bom
查看>>
MATLAB作图方法与技巧(一)
查看>>
上海淮海中路上苹果旗舰店门口欲砸一台IMAC电脑维权
查看>>
Google透露Android Market恶意程序扫描服务
查看>>
给mysql数据库字段值拼接前缀或后缀。 concat()函数
查看>>
迷宫问题
查看>>
【FZSZ2017暑假提高组Day9】猜数游戏(number)
查看>>
泛型子类_属性类型_重写方法类型
查看>>
eclipse-将同一个文件分屏显示
查看>>
对闭包的理解
查看>>
练习10-1 使用递归函数计算1到n之和(10 分
查看>>
Oracle MySQL yaSSL 不明细节缓冲区溢出漏洞2
查看>>
windows编程ASCII问题
查看>>
.net webService代理类
查看>>