数据科学与R语言

6. 调试、条件处理和防御式编程

2020-04-17  本文已影响0人  kkkkkkang

这章之前有章讲环境的,经常用到的概念和遇到的坑在前面或多或少都有涉及,所以跳过了。这章简写为debug

> f <- function(a) g(a)
> g <- function(b) h(b)
> h <- function(c) i(c)
> i <- function(d) "a" + d
> f(10)
#会报存在非数值参数的错误,点击Traceback,出现如下图的结果:从下往上看,错误发生在f()到i()逐渐调用,直至错误发生。点击Rerun with debug,可以运行到错误代码行
#如果没有使用Rstudio, traceback()函数照样可以实现
> traceback()
4: i(c) at #1
3: h(b) at #1
2: g(a) at #1
1: f(10)
> f <- function(a){
+   if (a ==0){
+     warning("a can not equal to zero")
+   }
+   a
+ }
> f(0)
[1] 0
Warning message:
In f(0) : a can not equal to zero
> options(warn =2)
> f(0)
> message2error <- function(code) {
+     withCallingHandlers(code, message = function(e) stop(e))
+ }
> 
> f <- function() g()
> g <- function() message("Hi!")
> g()
Hi!
> message2error(g())
 Error in message("Hi!") : Hi! 
> traceback()
10: stop(e) at #2
9: (function (e) 
   stop(e))(list(message = "Hi!\n", call = message("Hi!")))
8: signalCondition(cond)
7: doWithOneRestart(return(expr), restart)
6: withOneRestart(expr, restarts[[1L]])
5: withRestarts({
       signalCondition(cond)
       defaultHandler(cond)
   }, muffleMessage = function() NULL)
4: message("Hi!") at #1
3: g()
2: withCallingHandlers(code, message = function(e) stop(e)) at #2
1: message2error(g())
# try()
> f1 <- function(x) {
+     log(x)
+     10
+ }
> f1("x")
Error in log(x) : 数学函数中用了非数值参数
#遇到错误,抛出错误,然后并不继续执行
#try()可以忽略错误,继续执行下面的代码
> f2 <- function(x) {
+     try(log(x))
+     10
+ }
> f2("a")
Error in log(x) : 数学函数中用了非数值参数
[1] 10
#可以加上参数silent = TRUE来进制Error信息抛出
> f2 <- function(x) {
+   try(log(x),silent = TRUE)
+   10
+ }
> f2("a")
[1] 10
#try()中放置长代码,需要用{}
> try({
+     a <- 1
+     b <- "x"
+     a + b
+ })
Error in a + b : 二进列运算符中有非数值参数
success <- try(1 + 2)
failure <- try("a" + "b")
#> Error in "a" + "b" : non-numeric argument to binary operator
class(success)
#> [1] "numeric"
class(failure)
#> [1] "try-error"
elements <- list(1:10, c(-1, 10), c(TRUE, FALSE), letters)
results <- lapply(elements, log)
#> Warning in FUN(X[[i]], ...): NaNs produced
#> Error in FUN(X[[i]], ...): non-numeric argument to mathematical function
results <- lapply(elements, function(x) try(log(x)))
#> Warning in log(x): NaNs produced
#> Error in log(x) : non-numeric argument to mathematical function
is.error <- function(x) inherits(x, "try-error")
succeeded <- !vapply(results, is.error, logical(1))

# look at successful results
str(results[succeeded])
#> List of 3
#>  $ : num [1:10] 0 0.693 1.099 1.386 1.609 ...
#>  $ : num [1:2] NaN 2.3
#>  $ : num [1:2] 0 -Inf

# look at inputs that failed
str(elements[!succeeded])
#> List of 1
#>  $ : chr [1:26] "a" "b" "c" "d" ...
default <- NULL
try(default <- read.csv("possibly-bad-input.csv"), silent = TRUE)
show_condition <- function(code) {
  tryCatch(code,
    error = function(c) "error",
    warning = function(c) "warning",
    message = function(c) "message"
  )
}
show_condition(stop("!"))
#> [1] "error"
show_condition(warning("?!"))
#> [1] "warning"
show_condition(message("?"))
#> [1] "message"

# If no condition is captured, tryCatch returns the 
# value of the input
show_condition(10)
#> [1] 10
try2 <- function(code, silent = FALSE) {
  tryCatch(code, error = function(c) {
    msg <- conditionMessage(c)
    if (!silent) message(c)
    invisible(structure(msg, class = "try-error"))
  })
}

try2(1)
#> [1] 1
try2(stop("Hi"))
#> Error in doTryCatch(return(expr), name, parentenv, handler): Hi
try2(stop("Hi"), silent = TRUE)
read.csv2 <- function(file, ...) {
  tryCatch(read.csv(file, ...), error = function(c) {
    c$message <- paste0(c$message, " (in ", file, ")")
    stop(c)
  })
}
read.csv("code/dummy.csv")
#> Error in file(file, "rt"): cannot open the connection
read.csv2("code/dummy.csv")
#> Error in file(file, "rt"): cannot open the connection (in code/dummy.csv)
f <- function() g()
g <- function() h()
h <- function() stop("!")

tryCatch(f(), error = function(e) print(sys.calls()))
# [[1]] tryCatch(f(), error = function(e) print(sys.calls()))
# [[2]] tryCatchList(expr, classes, parentenv, handlers)
# [[3]] tryCatchOne(expr, names, parentenv, handlers[[1L]])
# [[4]] value[[3L]](cond)

withCallingHandlers(f(), error = function(e) print(sys.calls()))
# [[1]] withCallingHandlers(f(), 
#    error = function(e) print(sys.calls()))
# [[2]] f()
# [[3]] g()
# [[4]] h()
# [[5]] stop("!")
# [[6]] .handleSimpleError(
#    function (e) print(sys.calls()), "!", quote(h()))
# [[7]] h(simpleError(msg, call))
上一篇 下一篇

猜你喜欢

热点阅读