HOWTO · R
Usa la funzione tryCatch per la gestione delle condizioni in R
Questo articolo introduce come utilizzare la funzione tryCatch per la gestione delle condizioni in R.
In questa pagina
Usa tryCatch() in R quando un’espressione può segnalare una condizione e il codice deve fornire una risposta definita. Un gestore che interrompe l’espressione può trasformare un errore in un valore di ripiego, mentre finally può rilasciare una risorsa dopo un successo o un errore. È importante associare ogni gestore alla condizione che vuoi gestire e ricordare che il valore restituito dal gestore diventa il risultato di tryCatch().\n\n
Come tryCatch() gestisce le condizioni in R\n\nIn R, le condizioni comunicano eventi. stop() segnala un errore, warning() un avviso e message() un messaggio informativo. tryCatch() valuta un’espressione e cerca gestori associati alle classi di condizioni da gestire, come error, warning o message. La forma generale è tryCatch(expression, error = function(e) ..., finally = {...}); i gestori e l’argomento finally sono facoltativi. I gestori ricevono un oggetto condizione e conditionMessage(e) ne recupera il messaggio. Questi sono gestori che interrompono l’espressione: quando uno gestisce una condizione, la valutazione esce dall’espressione protetta e il valore del gestore diventa il risultato della chiamata. Un gestore di avvisi, quindi, impedisce anche l’esecuzione del resto dell’espressione. finally ha una funzione diversa: viene eseguito dopo la conclusione dell’espressione o del gestore e il suo valore non sostituisce il risultato.\n\n
Gestire gli errori con tryCatch()\n\nInserisci nel primo argomento l’operazione che potrebbe fallire e fai restituire al gestore error un valore di ripiego utile. La divisione per zero non è un esempio adatto di errore in R: la normale divisione numerica restituisce Inf. Passare del testo a log(), invece, segnala un errore.\n\nEsegui questo esempio:\n\n
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
cat(sum(c(2, 3)), "\n", sep = "")
\n
safeLog <- function(x) {
tryCatch(
log(x),
error = function(e) paste("Could not calculate log:", conditionMessage(e))
)
}
answer <- safeLog("not a number")
cat(answer, "\n", sep = "")
\nL’espressione protetta si interrompe quando si verifica l’errore, quindi eventuali istruzioni dopo log(x) al suo interno non vengono eseguite. Il gestore restituisce un valore di tipo carattere, che diventa answer. Il codice dopo la chiamata a tryCatch() può proseguire e usare quel risultato. Scegli un valore di ripiego che chi lo riceve possa distinguere da un normale risultato valido, per esempio un risultato strutturato o un valore sentinella chiaramente documentato.\n\n
Gestire avvisi e messaggi\n\nAnche gli avvisi e i messaggi sono condizioni, ma hanno scopi diversi. Un avviso segnala che un risultato potrebbe richiedere attenzione; un messaggio fornisce informazioni. Un gestore che interrompe l’espressione per uno dei due tipi ne termina la valutazione in quel punto. Se vuoi soltanto registrare un avviso e poi proseguire il calcolo, usa invece withCallingHandlers(): il suo gestore di chiamata può osservare la condizione mentre l’espressione originale continua.\n\nQuesto esempio gestisce entrambi i tipi di condizione e restituisce il valore del gestore:\n\n
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
conditionResult <- function() {
tryCatch(
{
warning("using an approximate value")
message("calculation complete")
42
},
warning = function(w) paste("Handled warning:", conditionMessage(w)),
message = function(m) paste("Handled message:", conditionMessage(m))
)
}
cat(conditionResult(), "\n", sep = "")
\nIn questo caso viene selezionato per primo il gestore degli avvisi, quindi non si arriva né al messaggio né all’espressione che restituisce il valore. Per gestire una condizione senza interrompere l’esecuzione, usa withCallingHandlers(): il suo gestore di chiamata può osservare la condizione mentre l’espressione protetta prosegue. Per sopprimere un avviso o un messaggio, invoca dal gestore il relativo restart con invokeRestart("muffleWarning") o invokeRestart("muffleMessage"), rispettivamente. Al contrario, un gestore che interrompe l’espressione in tryCatch() esce dall’espressione protetta e restituisce il proprio valore. Non dare per scontato che aggiungere un gestore si limiti a registrare una condizione e lasci terminare l’espressione protetta.\n\n
Usare finally per la pulizia\n\nUsa finally per le operazioni che devono essere eseguite al termine del tentativo, sia che abbia successo sia che segnali una condizione gestita. La pulizia dovrebbe essere sicura anche se la preparazione fallisce a metà. Per una connessione, inizializza la variabile prima del tentativo e chiudi la connessione solo se è stata aperta:\n\n
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
path <- tempfile()
writeLines("first line", path)
con <- NULL
contents <- tryCatch(
{
con <- file(path, open = "r")
readLines(con)
},
error = function(e) paste("Read failed:", conditionMessage(e)),
finally = {
if (!is.null(con) && isOpen(con)) close(con)
unlink(path)
}
)
print(contents)
\nLa connessione viene chiusa prima di rimuovere il file temporaneo e unlink() è sicura anche se un’operazione precedente è fallita. Nel codice applicativo, limita la pulizia al rilascio delle risorse; evita di restituire da finally il risultato utile, perché quel valore viene ignorato.\n\n