Как написать trycatch в R
Я хочу писать trycatch
код для устранения ошибки при загрузке из интернета.
url <- c(
"http://stat.ethz.ch/R-manual/R-devel/library/base/html/connections.html",
"http://en.wikipedia.org/wiki/Xz")
y <- mapply(readLines, con=url)
эти два оператора выполняются успешно. Ниже я создаю несуществующий веб-адрес:
url <- c("xxxxx", "http://en.wikipedia.org/wiki/Xz")
url[1]
не существует. Как можно написать trycatch
цикл (функция) так что:
- когда URL-адрес является неправильным, вывод будет: "URL-адрес является неправильным, не могут сделать".
- когда URL-адрес неверен, код не останавливается, но продолжает скачать до конца списка URL-адресов?
4 ответа:
ну тогда: добро пожаловать в мир R; -)
вот ты где
настройка код
urls <- c( "http://stat.ethz.ch/R-manual/R-devel/library/base/html/connections.html", "http://en.wikipedia.org/wiki/Xz", "xxxxx" ) readUrl <- function(url) { out <- tryCatch( { # Just to highlight: if you want to use more than one # R expression in the "try" part then you'll have to # use curly brackets. # 'tryCatch()' will return the last evaluated expression # in case the "try" part was completed successfully message("This is the 'try' part") readLines(con=url, warn=FALSE) # The return value of `readLines()` is the actual value # that will be returned in case there is no condition # (e.g. warning or error). # You don't need to state the return value via `return()` as code # in the "try" part is not wrapped insided a function (unlike that # for the condition handlers for warnings and error below) }, error=function(cond) { message(paste("URL does not seem to exist:", url)) message("Here's the original error message:") message(cond) # Choose a return value in case of error return(NA) }, warning=function(cond) { message(paste("URL caused a warning:", url)) message("Here's the original warning message:") message(cond) # Choose a return value in case of warning return(NULL) }, finally={ # NOTE: # Here goes everything that should be executed at the end, # regardless of success or error. # If you want more than one expression to be executed, then you # need to wrap them in curly brackets ({...}); otherwise you could # just have written 'finally=<expression>' message(paste("Processed URL:", url)) message("Some other message at the end") } ) return(out) }
применение кода
> y <- lapply(urls, readUrl) Processed URL: http://stat.ethz.ch/R-manual/R-devel/library/base/html/connections.html Some other message at the end Processed URL: http://en.wikipedia.org/wiki/Xz Some other message at the end URL does not seem to exist: xxxxx Here's the original error message: cannot open the connection Processed URL: xxxxx Some other message at the end Warning message: In file(con, "r") : cannot open file 'xxxxx': No such file or directory
расследование производства
> head(y[[1]]) [1] "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">" [2] "<html><head><title>R: Functions to Manipulate Connections</title>" [3] "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">" [4] "<link rel=\"stylesheet\" type=\"text/css\" href=\"R.css\">" [5] "</head><body>" [6] "" > length(y) [1] 3 > y[[3]] [1] NA
дополнительная информация
tryCatch
tryCatch
возвращает значение, связанное с исполнениемexpr
если нет ошибки или предупреждения. В этом случае определенные возвращаемые значения (см.return(NA)
выше) может быть указывается путем предоставления соответствующей функции обработчика (см. аргументыerror
иwarning
на?tryCatch
). Это могут быть уже существующие функции, но вы также можете определить их вtryCatch()
(как я сделал выше).последствия выбора конкретных возвращаемых значений функций обработчика
как мы уже указали, что
NA
должен быть возвращен в случае ошибки, третий элементy
иNA
. Если бы мы выбралиNULL
будет возвращаемое значение, длинаy
было2
вместо3
какlapply()
будет просто "игнорировать" возвращаемые значения, которыеNULL
. Также обратите внимание, что если вы не укажете явно возвращаемое значение черезreturn()
, функции обработчика вернутNULL
(т. е. в случае ошибки или предупреждения)."нежелательных" предупреждение
как
warn=FALSE
кажется, не имеет никакого эффекта, альтернатива способ подавить предупреждение (которое в данном случае не представляет особого интереса) заключается в использованииsuppressWarnings(readLines(con=url))
вместо
readLines(con=url, warn=FALSE)
несколько выражений
обратите внимание, что вы также можете разместить несколько выражений в " фактической части выражений "(аргумент
expr
наtryCatch()
) если вы обернете их в фигурные скобки (так же, как я проиллюстрировал вfinally
часть).
R использует функции для реализации блока try-catch:
синтаксис выглядит так:
result = tryCatch({ expr }, warning = function(warning_condition) { warning-handler-code }, error = function(error_condition) { error-handler-code }, finally={ cleanup-code })
в tryCatch() есть два ‘условия’, которые могут быть обработаны: "предупреждения" и "ошибки". При написании каждого блока кода важно понимать состояние выполнения и область действия. @source
здесь идет простой пример:
# Do something, or tell me why it failed my_update_function <- function(x){ tryCatch( # This is what I want to do: y = x * 2 return(y) , # ... but if an error occurs, tell me what happened: error=function(error_message) { message("My message is here!") message("And below is the error message from R:") message(error_message) return(NA) } ) }
Если вы также хотите захватить "предупреждение", просто добавьте
warning=
аналогичноerror=
часть.
Так как я только что потерял два дня своей жизни, пытаясь решить для tryCatch для функции irr, я подумал, что должен поделиться своей мудростью (и чего не хватает). FYI-irr является фактической функцией от FinCal в этом случае, когда получены ошибки в нескольких случаях на большом наборе данных.
настройка tryCatch как часть функции. Например:
irr2 <- function (x) { out <- tryCatch(irr(x), error = function(e) NULL) return(out) }
чтобы ошибка (или предупреждение) работала, вам действительно нужно создать функцию. Я изначально за ошибку часть просто написала
error = return(NULL)
и все значения вернулись null.не забудьте создать суб-выход (например, мой "выход") и
return(out)
.