Menu
Coddy logo textTech

Перехват ошибок с помощью tryCatch()

Часть раздела Логика и потоки выполнения путешествия по R на Coddy. Урок 53 из 64.

tryCatch(expr, error = function(e) ...) выполняет expr. Если возникает ошибка, вместо него запускается обработчик, и его значение становится результатом, а выполнение скрипта продолжается:

safe_sqrt <- function(x) {
  tryCatch(sqrt(x), error = function(e) NA)
}
print(safe_sqrt(16))
print(safe_sqrt("a"))
print("still running")

Результат:

[1] 4
[1] NA
[1] "still running"

Обработчик получает ошибку как e, а conditionMessage(e) возвращает её текст сообщения:

result <- tryCatch(
  stop("file not found"),
  error = function(e) paste("Problem:", conditionMessage(e))
)
print(result)

Вывод:

[1] "Problem: file not found"

Оборачивай только тот вызов, который может завершиться ошибкой, и перехватывай её там, где ты можешь сделать что-то полезное, например вернуть значение по умолчанию или вывести сообщение для пользователя:

to_number <- function(s) {
  tryCatch({
    if (s == "") stop("empty input")
    as.integer(s)
  }, error = function(e) -1L)
}
print(to_number("42"))
print(to_number(""))

Результат:

[1] 42
[1] -1

В цикле tryCatch() позволяет одному ошибочному элементу завершиться с ошибкой, пока остальные по-прежнему обрабатываются:

inputs <- list(4, "x", 9)
for (v in inputs) {
  r <- tryCatch(sqrt(v), error = function(e) "not a number")
  cat(format(v), "->", r, "\n")
}

Вывод:

4 -> 2 
x -> not a number 
9 -> 3 
challenge icon

Задание

Легко

Завершите safe_divide(a, b). Используйте tryCatch(): внутри него вызовите ошибку division by zero, когда b равно 0, а в противном случае вычислите a / b. Обработчик возвращает Error: , за которым следует сообщение. Верните результат, округлённый до двух знаков после запятой, в виде текста, например 3.33, или текст ошибки.

Предоставленный код считывает пары чисел, такие как 10/3, разделённые запятыми, и выводит результат для каждой пары в отдельной строке.

Попробуйте сами

safe_divide <- function(a, b) {
  # Напишите ваш код здесь
  ""
}

# Предоставленный код ввода/вывода: оставьте его как есть
input <- suppressWarnings(readLines(file("stdin")))
for (pair in strsplit(input[1], ",")[[1]]) {
  p <- as.numeric(strsplit(pair, "/")[[1]])
  cat(safe_divide(p[1], p[2]), "\n", sep = "")
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Логика и потоки выполнения

Потренируйтесь самостоятельно: Онлайн-компилятор R