Bem, então: bem-vindo ao mundo R ;-)
Aqui está
Configurando o código
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)
}
Aplicando o código
> 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
Investigando a saída
> 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
Observações adicionais
tryCatch
tryCatch
retorna o valor associado à execução, a expr
menos que haja um erro ou aviso. Nesse caso, valores de retorno específicos (veja return(NA)
acima) podem ser especificados fornecendo uma função de manipulador respectiva (consulte argumentos error
e warning
in ?tryCatch
). Podem ser funções que já existem, mas você também pode defini-las dentrotryCatch()
(como fiz acima).
As implicações da escolha de valores de retorno específicos das funções do manipulador
Como especificamos que NA
deve ser retornado em caso de erro, o terceiro elemento y
é NA
. Se tivéssemos escolhido NULL
para ser o valor de retorno, o comprimento y
seria apenas ter sido 2
em vez de 3
como lapply()
simplesmente "ignorar" valores de retorno que são NULL
. Observe também que, se você não especificar um valor de retorno explícito via return()
, as funções do manipulador retornarão NULL
(ou seja, no caso de um erro ou condição de aviso).
Mensagem de aviso "indesejado"
Como warn=FALSE
não parece ter efeito, uma maneira alternativa de suprimir o aviso (que neste caso não é realmente interessante) é usar
suppressWarnings(readLines(con=url))
ao invés de
readLines(con=url, warn=FALSE)
Várias expressões
Observe que você também pode colocar várias expressões na "parte de expressões reais" (argumento expr
de tryCatch()
) se as envolver entre colchetes (como ilustrado na finally
peça).
paste
funções termina com um espaço, por que não omitir o espaço e osep=""
?paste0
para isso!paste0()
está na base. Internamente, ambospaste()
epaste0()
chamedo_paste
em paste.c . A única diferença épaste0()
que não passa umsep
argumento.readLines(con=url, warn=FALSE)
que realmente pode dar errado). Então, se você quiser adicionar uma mensagem, você precisaria armazenado o valor retun real em uma variável:out <- readLines(con=url, warn=FALSE)
seguido pormessage("Everything worked")
seguido porout
, a fim de tornar este o último objeto que é realmente devolvidoR usa funções para implementar o bloco try-catch:
A sintaxe é algo como isto:
No tryCatch (), existem duas 'condições' que podem ser tratadas: 'avisos' e 'erros'. O importante a entender ao escrever cada bloco de código é o estado de execução e o escopo. @fonte
fonte
error-handler-code
porcat("web url is wrong, can't get")
tryCatch
possui uma estrutura de sintaxe um pouco complexa. No entanto, uma vez que entendemos as quatro partes que constituem uma chamada tryCatch completa, como mostrado abaixo, fica fácil lembrar:expr : [ obrigatório ] código (s) R a ser avaliado
erro : [ Opcional ] O que deve ser executado se ocorrer um erro ao avaliar os códigos em expr
aviso : [ Opcional ] O que deve ser executado se um aviso ocorrer durante a avaliação dos códigos em expr
finalmente : [ Opcional ] O que deve ser executado antes de sair da chamada tryCatch, independentemente de se o expr for executado com sucesso, com um erro ou com um aviso
Assim, um exemplo de brinquedo, para calcular o log de um valor, pode parecer com:
Agora, executando três casos:
Um caso válido
Um caso de "aviso"
Um caso de "erro"
Eu escrevi sobre alguns casos de uso úteis que uso regularmente. Encontre mais detalhes aqui: https://rsangole.netlify.com/post/try-catch/
Espero que isso seja útil.
fonte
Aqui está um exemplo direto :
Se você também deseja capturar um "aviso", basta adicionar
warning=
semelhante àerror=
peça.fonte
expr
peça, pois existem duas linhas em vez de uma?Error: unexpected ')' in " )"
eError: unexpected ')' in " )"
. Adicionar um par de colchetes resolve o problema.Como acabei de perder dois dias da minha vida tentando resolver o tryCatch para uma função irr, achei que deveria compartilhar minha sabedoria (e o que está faltando). FYI - irr é uma função real do FinCal, neste caso, onde houve erros em alguns casos em um grande conjunto de dados.
Configure o tryCatch como parte de uma função. Por exemplo:
Para que o erro (ou aviso) funcione, você realmente precisa criar uma função. Eu originalmente para a parte do erro acabei de escrever
error = return(NULL)
e TODOS os valores voltaram nulos.Lembre-se de criar uma sub-saída (como minha "saída") e para
return(out)
.fonte