withCallingHandlers() y reinicios
Use withCallingHandlers() para gestionar condiciones no locales.
withCallingHandlers() y reinicios es una lección gratuita de R Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de R Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de R Academy incluye 4 lecciones en total.
tryCatch frente a withCallingHandlers
La diferencia clave es que tryCatch() establece una salida no local: una vez capturada una condición, el control sale de la expresión y no regresa a ella. withCallingHandlers() mantiene intacta la pila de llamadas y puede reanudar la ejecución después de gestionar la condición.
# 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 la ejecución
Con withCallingHandlers(), el controlador se ejecuta, pero la ejecución continúa después de que se señale la condición, a menos que el propio controlador lance un error o invoque un reinicio. La pila de llamadas no se desenrolla.
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')
})Reinicio muffleWarning
Llamar a invokeRestart('muffleWarning') dentro de un controlador de advertencias evita que el controlador predeterminado de R imprima la advertencia. Sin esta llamada, después de ejecutarse su controlador, R seguiría imprimiendo la advertencia mediante su mecanismo predeterminado.
# Without muffleWarning: warning still shows after handler
withCallingHandlers({
warning('test')
}, warning = function(w) {
cat('Handler ran\n')
# no muffleWarning: default handler still fires
})Reinicio muffleMessage
De forma similar, invokeRestart('muffleMessage') dentro de un controlador de mensajes silencia el mensaje después de que su controlador personalizado lo procese. Este es el mecanismo en el que se basa suppressMessages().
withCallingHandlers({
message('Progress: 50%')
message('Progress: 100%')
}, message = function(m) {
cat('[LOG]', trimws(m$message), '\n')
invokeRestart('muffleMessage')
})Registrar advertencias sin detener la ejecución
Un uso práctico de withCallingHandlers() consiste en recopilar advertencias en un vector de registro mientras se permite que el código termine. tryCatch() se detendría ante la primera advertencia; withCallingHandlers() las recopila todas.
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')Concepto de invokeRestart()
Los reinicios son estrategias de recuperación predefinidas que puede ofrecer el código que señala la condición. invokeRestart(name) selecciona una de esas estrategias. Entre los reinicios integrados se incluyen 'muffleWarning' y 'muffleMessage'; puede definir reinicios personalizados 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')
)Combinar withCallingHandlers y tryCatch
Puede anidar ambos: use withCallingHandlers() en el exterior para registrar o contar condiciones, y tryCatch() en el interior para proporcionar un valor alternativo. El controlador externo ve primero la condición.
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')Clases de condición personalizadas
Puede crear clases de condición personalizadas llamando a structure() sobre una lista con la clase c('myError', 'error', 'condition'). Los controladores buscan coincidencias por clase, por lo que las clases personalizadas permiten capturar tipos de error específicos sin capturar todos los errores.
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')
)Cuándo usar withCallingHandlers
Use withCallingHandlers() cuando quiera observar o registrar condiciones sin detener la ejecución. Use tryCatch() cuando quiera recuperarse de una condición y devolver un valor alternativo. Resuelven problemas diferentes.
# 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 cadena de señalización de condiciones
Cuando se señala una condición, R recorre la pila de llamadas hacia arriba en busca de controladores. Los controladores de withCallingHandlers() se ejecutan en el contexto dinámico, con la pila de llamadas intacta. Los controladores de tryCatch() se ejecutan después del desenrollado; el contexto original ya no existe.
# 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()Implementación de suppressWarnings()
suppressWarnings(expr) es esencialmente withCallingHandlers(expr, warning = function(w) invokeRestart('muffleWarning')). Comprender esto le permite crear sus propias variantes que supriman solo determinados tipos de advertencia.
# 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')
)Comprobación rápida
¿Cuál es la diferencia principal entre withCallingHandlers() y tryCatch()?
Reinicios: conclusiones clave
Conclusiones clave sobre withCallingHandlers y los reinicios:
withCallingHandlers()= controlador local, pila de llamadas intacta y posibilidad de continuar la ejecucióntryCatch()= salida no local, pila desenrollada y posibilidad de devolver un valor alternativoinvokeRestart('muffleWarning')suprime la impresión predeterminada de la advertenciainvokeRestart('muffleMessage')suprime la impresión predeterminada del mensaje- Use
withCallingHandlers()para recopilar o registrar todas las condiciones sin detener la ejecución - Las clases de condición personalizadas permiten capturar selectivamente tipos de error específicos
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')Preguntas frecuentes
¿La lección «withCallingHandlers() y reinicios» es gratis?
Sí — el texto completo de «withCallingHandlers() y reinicios» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de R Academy, actualiza a CoddyKit PRO. El curso de R Academy incluye 4 lecciones en total.
¿Qué aprenderé en «withCallingHandlers() y reinicios»?
Use withCallingHandlers() para gestionar condiciones no locales. Practicas R Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar R Academy?
No se requiere experiencia previa. R Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «withCallingHandlers() y reinicios»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de R Academy?
Sí. Cada lección de R Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Errores, advertencias y mensajes en R
- tryCatch() para recuperar errores
- withCallingHandlers() y reinicios
- Escritura de funciones robustas con stop() y warning()