withCallingHandlers() e i restart
Usi withCallingHandlers() per gestire condizioni non locali.
withCallingHandlers() e i restart è una lezione R Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento R Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso R Academy include 4 lezioni in totale.
tryCatch e withCallingHandlers
La differenza fondamentale è questa: tryCatch() stabilisce un uscita non locale; quando una condizione viene intercettata, il controllo passa fuori dall'espressione e non vi ritorna. withCallingHandlers() mantiene intatto lo stack delle chiamate e può riprendere l'esecuzione dopo la gestione.
# tryCatch: execution does NOT continue after warning
tryCatch({
warning('first')
cat('This line is never reached\n')
}, warning = function(w) cat('tryCatch caught:', w$message, '\n'))withCallingHandlers mantiene l'esecuzione
Con withCallingHandlers(), il gestore viene eseguito, ma l'esecuzione continua dopo la segnalazione della condizione, a meno che il gestore stesso non generi un errore o invochi un restart. Lo stack delle chiamate non viene srotolato.
withCallingHandlers({
warning('first warning')
cat('Execution continues here\n')
warning('second warning')
cat('And here too\n')
}, warning = function(w) {
cat('Handler saw:', w$message, '\n')
invokeRestart('muffleWarning')
})Restart muffleWarning
Chiamare invokeRestart('muffleWarning') all'interno di un gestore degli avvisi impedisce che l'avviso venga stampato dal gestore predefinito di R. Senza questa chiamata, dopo l'esecuzione del gestore personalizzato R stamperebbe comunque l'avviso tramite il proprio meccanismo predefinito.
# Without muffleWarning: warning still shows after handler
withCallingHandlers({
warning('test')
}, warning = function(w) {
cat('Handler ran\n')
# no muffleWarning: default handler still fires
})Restart muffleMessage
Analogamente, invokeRestart('muffleMessage') all'interno di un gestore dei messaggi silenzia il messaggio dopo che il gestore personalizzato lo ha elaborato. Questo è il meccanismo alla base di suppressMessages().
withCallingHandlers({
message('Progress: 50%')
message('Progress: 100%')
}, message = function(m) {
cat('[LOG]', trimws(m$message), '\n')
invokeRestart('muffleMessage')
})Registrare gli avvisi senza interrompere l'esecuzione
Un uso pratico di withCallingHandlers() consiste nel raccogliere gli avvisi in un vettore di log, consentendo al codice di terminare. tryCatch() si fermerebbe al primo avviso; withCallingHandlers() li raccoglie tutti.
warnings_log <- character(0)
result <- withCallingHandlers({
x <- log(-1)
y <- sqrt(-4)
c(x, y)
}, warning = function(w) {
warnings_log <<- c(warnings_log, w$message)
invokeRestart('muffleWarning')
})
cat('Warnings logged:', length(warnings_log), '\n')
cat(warnings_log, sep = '\n')Il concetto di invokeRestart()
I restart sono strategie di recupero predefinite che il codice che segnala la condizione può offrire. invokeRestart(name) seleziona una di queste strategie. I restart integrati includono 'muffleWarning' e 'muffleMessage'; è possibile definirne di personalizzati con withRestarts().
# withRestarts() offers named recovery options
divide_safe <- function(x, y) {
withRestarts(
{
if (y == 0) stop('division by zero')
x / y
},
use_zero = function() 0,
use_na = function() NA
)
}
# A handler can pick a restart
withCallingHandlers(
divide_safe(10, 0),
error = function(e) invokeRestart('use_zero')
)Combinare withCallingHandlers e tryCatch
È possibile annidare i due strumenti: utilizzi withCallingHandlers() all'esterno per registrare o contare le condizioni e tryCatch() all'interno per fornire un valore alternativo. Il gestore esterno vede per primo la condizione.
n_warnings <- 0L
result <- withCallingHandlers(
tryCatch(log(-1), warning = function(w) -999),
warning = function(w) {
n_warnings <<- n_warnings + 1L
cat('Logged warning #', n_warnings, '\n')
}
)
cat('Result:', result, '\n')Classi di condizioni personalizzate
È possibile creare classi di condizioni personalizzate chiamando structure() su una lista con classe c('myError', 'error', 'condition'). I gestori fanno corrispondere le classi, quindi le classi personalizzate consentono di intercettare tipi specifici di errore senza intercettare tutti gli errori.
my_error <- function(msg, data = NULL) {
structure(
class = c('my_error', 'error', 'condition'),
list(message = msg, data = data)
)
}
tryCatch(
stop(my_error('custom error', data = 42)),
my_error = function(e) cat('Custom handler, data=', e$data, '\n'),
error = function(e) cat('Generic handler\n')
)Quando utilizzare withCallingHandlers
Utilizzi withCallingHandlers() quando desidera osservare o registrare le condizioni senza interrompere l'esecuzione. Utilizzi tryCatch() quando desidera recuperare da una condizione e restituire un valore alternativo. Risolvono problemi diversi.
# withCallingHandlers: observe all, continue
withCallingHandlers(
for (x in c(4, -1, 9, -4)) cat(suppressWarnings(sqrt(x)), ''),
warning = function(w) cat('[warn]', '')
)
cat('\n')La catena di segnalazione delle condizioni
Quando viene segnalata una condizione, R risale lo stack delle chiamate alla ricerca dei gestori. I gestori di withCallingHandlers() vengono eseguiti nel contesto dinamico, con lo stack delle chiamate intatto. I gestori di tryCatch() vengono eseguiti dopo lo srotolamento dello stack: il contesto originale non è più disponibile.
# Demonstrate: withCallingHandlers handler can see full stack
f <- function() {
withCallingHandlers(
g(),
warning = function(w) {
cat('Caught in f, stack length:', sys.nframe(), '\n')
invokeRestart('muffleWarning')
}
)
}
g <- function() warning('from g')
f()Implementazione di suppressWarnings()
suppressWarnings(expr) equivale essenzialmente a withCallingHandlers(expr, warning = function(w) invokeRestart('muffleWarning')). Comprendere questo meccanismo consente di creare varianti personalizzate che sopprimono solo determinati tipi di avviso.
# Suppress only NaN warnings, not others
suppress_nan_warn <- function(expr) {
withCallingHandlers(expr, warning = function(w) {
if (grepl('NaN', conditionMessage(w)))
invokeRestart('muffleWarning')
})
}
suppress_nan_warn(log(-1)) # NaN warning suppressed
tryCatch(
suppress_nan_warn(warning('other issue')),
warning = function(w) cat('Other warning kept:', w$message, '\n')
)Verifica rapida
Qual è la differenza principale tra withCallingHandlers() e tryCatch()?
Restart: punti chiave
Punti chiave di withCallingHandlers e dei restart:
withCallingHandlers()= gestore locale, stack delle chiamate intatto, l'esecuzione può continuaretryCatch()= uscita non locale, stack srotolato, può restituire un valore alternativoinvokeRestart('muffleWarning')sopprime la stampa predefinita dell'avvisoinvokeRestart('muffleMessage')sopprime la stampa predefinita del messaggio- Utilizzi
withCallingHandlers()per raccogliere o registrare tutte le condizioni senza interrompere l'esecuzione - Le classi di condizioni personalizzate consentono di intercettare selettivamente tipi specifici di errore
log_vec <- character(0)
withCallingHandlers({
message('start')
warning('low memory')
message('end')
}, message = function(m) {
log_vec <<- c(log_vec, paste('MSG:', trimws(m$message)))
invokeRestart('muffleMessage')
}, warning = function(w) {
log_vec <<- c(log_vec, paste('WARN:', w$message))
invokeRestart('muffleWarning')
})
cat(log_vec, sep = '\n')Impara R con un tutor IA — gratis
Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.
- Corsi
- 43
- Lezioni
- 159
Domande Frequenti
La lezione «withCallingHandlers() e i restart» è gratuita?
Sì — il testo completo di «withCallingHandlers() e i restart» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso R Academy, passa a CoddyKit PRO. Il corso R Academy include 4 lezioni in totale.
Cosa imparerò in «withCallingHandlers() e i restart»?
Usi withCallingHandlers() per gestire condizioni non locali. Eserciti R Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare R Academy?
Non è richiesta alcuna esperienza precedente. R Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «withCallingHandlers() e i restart»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione R Academy?
Sì. Ogni lezione R Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Errori, avvisi e messaggi in R
- tryCatch() per il recupero dagli errori
- withCallingHandlers() e i restart
- Scrittura di funzioni robuste con stop() e warning()