attempt()
is a wrapper around base try()
that allows you to insert a custom messsage on error.
attempt(log("a"))
#> Error: non-numeric argument to mathematical function
# Error: non-numeric argument to mathematical function
attempt(log("a"), msg = "Nop !")
#> Error: Nop !
# Error: Nop !
You can make it verbose (i.e. returning the expression):
attempt(log("a"), msg = "Nop !", verbose = TRUE)
#> Error in log("a"): Nop !
# Error in log("a"): Nop !
Of course the result is returned if there is one:
As with try()
, the result can be saved as an error
object:
a <- attempt(log("a"), msg = "Nop !", verbose = TRUE)
#> Error in log("a"): Nop !
a
#> [1] "Error in log(\"a\"): Nop !\n"
#> attr(,"class")
#> [1] "try-error"
#> attr(,"condition")
#> <simpleError in log("a"): Nop !>
# [1] "Error in log(\"a\"): Nop !\n"
# attr(,"class")
# [1] "try-error"
# attr(,"condition")
# <simpleError in log("a"): Nop !>
You can check if the result is an error with
is_try_error()
silent_attempt()
is a wrapper around
silently()
(see further down for more info) and
attempt()
. It attempts to run the expr, stays silent if the
expression succeeds, and returns error or warnings if any.
You can write a try catch with these params:
expr
the expression to be evaluated.e
a mapper or a function evaluated when an error
occurs.w
a mapper or a function evaluated when a warning
occurs.f
a mapper or an expression which is always evaluated
before returning or exitingIn .e
and .f
, the .x
refers to
the error / warning object.
try_catch(
expr = log("a"),
.e = ~ paste0("There is an error: ", .x),
.w = ~ paste0("This is a warning: ", .x)
)
#> [1] "There is an error: Error in log(\"a\"): non-numeric argument to mathematical function\n"
# [1] "There is an error: Error in log(\"a\"): non-numeric argument to mathematical function\n"
try_catch(
log("a"),
.e = ~ stop(.x),
.w = ~ warning(.x)
)
#> Error in log("a"): non-numeric argument to mathematical function
# Error in log("a") : non-numeric argument to mathematical function
try_catch(
matrix(1:3, nrow = 2),
.e = ~ print(.x),
.w = ~ print(.x)
)
#> <simpleWarning in matrix(1:3, nrow = 2): data length [3] is not a sub-multiple or multiple of the number of rows [2]>
#<simpleWarning in matrix(1:3, nrow = 2): data length [3] is not a sub-multiple or multiple of the number of rows [2]>
try_catch(
expr = 2 + 2,
.f = ~ print("Using R for addition... ok I'm out!")
)
#> [1] "Using R for addition... ok I'm out!"
#> [1] 4
# [1] "Using R for addition... ok I'm out!"
# [1] 4
As usual, the handlers are set only if you call them:
try_catch(matrix(1:3, nrow = 2), .e = ~ print("error"))
#> Warning in matrix(1:3, nrow = 2): data length [3] is not a sub-multiple or
#> multiple of the number of rows [2]
#> [,1] [,2]
#> [1,] 1 3
#> [2,] 2 1
# [,1] [,2]
# [1,] 1 3
# [2,] 2 1
# Warning message:
# In matrix(1:3, nrow = 2) :
# data length [3] is not a sub-multiple or multiple of the number of rows [2]
{attempt}
is flexible in how you can specify your
arguments.
You can, as you do with {base}
tryCatch()
,
use a plain old function:
try_catch(
log("a"),
.e = function(e) {
print(paste0("There is an error: ", e))
print("Ok, let's save this")
time <- Sys.time()
a <- paste("+ At", time, ", \nError:", e)
# write(a, "log.txt", append = TRUE) # commented to prevent log.txt creation
print(paste("log saved on log.txt at", time))
print("let's move on now")
}
)
#> [1] "There is an error: Error in log(\"a\"): non-numeric argument to mathematical function\n"
#> [1] "Ok, let's save this"
#> [1] "log saved on log.txt at 2024-11-21 04:35:07.46578"
#> [1] "let's move on now"
# [1] "There is an error: Error in log(\"a\"): non-numeric argument to mathematical function\n"
# [1] "Ok, let's save this"
# [1] "log saved on log.txt at 2018-01-30 16:59:13"
# [1] "let's move on now"
You can even mix both:
try_catch(
log("a"),
.e = function(e) {
paste0("There is an error: ", e)
},
.f = ~ print("I'm not sure you can do that pal !")
)
#> [1] "I'm not sure you can do that pal !"
#> [1] "There is an error: Error in log(\"a\"): non-numeric argument to mathematical function\n"
# [1] "I'm not sure you can do that pal !"
# [1] "There is an error: Error in log(\"a\"): non-numeric argument to mathematical function\n"
try_catch(
log("a"),
.e = ~ paste0("There is an error: ", .x),
.f = function() print("I'm not sure you can do that pal !")
)
#> [1] "I'm not sure you can do that pal !"
#> [1] "There is an error: Error in log(\"a\"): non-numeric argument to mathematical function\n"
# [1] "I'm not sure you can do that pal !"
# [1] "There is an error: Error in log(\"a\"): non-numeric argument to mathematical function\n"
try_catch_df()
try_catch_df()
returns a tibble with the call, the error
message if any, the warning message if any, and the value of the
evaluated expression or “error”. The values will always be contained in
a list-column.
res_log <- try_catch_df(log("a"))
res_log
#> call error warning value
#> 1 log("a") non-numeric argument to mathematical function NA error
res_log$value
#> [[1]]
#> [1] "error"
res_matrix <- try_catch_df(matrix(1:3, nrow = 2))
res_matrix
#> call error
#> 1 matrix(1:3, nrow = 2) NA
#> warning
#> 1 data length [3] is not a sub-multiple or multiple of the number of rows [2]
#> value
#> 1 1, 2, 3, 1
res_matrix$value
#> [[1]]
#> [,1] [,2]
#> [1,] 1 3
#> [2,] 2 1
res_success <- try_catch_df(log(1))
res_success
#> call error warning value
#> 1 log(1) NA NA 0
res_success$value
#> [[1]]
#> [1] 0
map_try_catch()
map_try_catch()
and map_try_catch_df()
allow you to map on a list of arguments l
, to be evaluated
by the function in fun
.
map_try_catch(l = list(1, 3, "a"), fun = log, .e = ~.x)
#> [[1]]
#> [1] 0
#>
#> [[2]]
#> [1] 1.098612
#>
#> [[3]]
#> <simpleError in .Primitive("log")("a"): non-numeric argument to mathematical function>
map_try_catch_df(list(1, 3, "a"), log)
#> call error warning
#> 1 .Primitive("log")(1) <NA> NA
#> 2 .Primitive("log")(3) <NA> NA
#> 3 .Primitive("log")("a") non-numeric argument to mathematical function NA
#> value
#> 1 0
#> 2 1.098612
#> 3 error