withCallingHandlers() e reinicializações
Use withCallingHandlers() para o tratamento não local de condições.
withCallingHandlers() e reinicializações é uma aula grátis de R Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de R Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de R Academy inclui 4 aulas no total.
tryCatch versus withCallingHandlers
A principal diferença é que tryCatch() estabelece uma saída não local: assim que uma condição é capturada, o controle sai da expressão e não retorna a ela. withCallingHandlers() mantém a pilha de chamadas intacta e pode retomar a execução depois do tratamento.
# 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 mantém a execução
Com withCallingHandlers(), o manipulador é executado, mas a execução continua depois que a condição é sinalizada (a menos que o próprio manipulador lance um erro ou invoque uma reinicialização). A pilha de chamadas não é desfeita.
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')
})Reinicialização muffleWarning
Chamar invokeRestart('muffleWarning') dentro de um manipulador de avisos impede que o aviso seja exibido pelo manipulador padrão de R. Sem isso, depois que o seu manipulador for executado, R ainda exibirá o aviso por meio do seu mecanismo padrão.
# Without muffleWarning: warning still shows after handler
withCallingHandlers({
warning('test')
}, warning = function(w) {
cat('Handler ran\n')
# no muffleWarning: default handler still fires
})Reinicialização muffleMessage
Da mesma forma, invokeRestart('muffleMessage') dentro de um manipulador de mensagens silencia a mensagem depois que o seu manipulador personalizado a processa. Esse é o mecanismo por trás de suppressMessages().
withCallingHandlers({
message('Progress: 50%')
message('Progress: 100%')
}, message = function(m) {
cat('[LOG]', trimws(m$message), '\n')
invokeRestart('muffleMessage')
})Registrando avisos sem interromper
Um uso prático de withCallingHandlers() é coletar avisos em um vetor de registro enquanto permite que o código seja concluído. tryCatch() pararia no primeiro aviso; withCallingHandlers() coleta todos eles.
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')Conceito de invokeRestart()
As reinicializações são estratégias de recuperação predefinidas que o código que sinaliza a condição pode oferecer. invokeRestart(name) seleciona uma dessas estratégias. As reinicializações integradas incluem 'muffleWarning' e 'muffleMessage'; você pode definir reinicializações personalizadas com 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')
)Combinando withCallingHandlers e tryCatch
Você pode aninhar os dois: use withCallingHandlers() externamente para registrar ou contar condições, e tryCatch() internamente para fornecer um valor alternativo. O manipulador externo vê a condição primeiro.
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')Classes de condição personalizadas
Você pode criar classes de condição personalizadas chamando structure() em uma lista com a classe c('myError', 'error', 'condition'). Os manipuladores fazem correspondência pela classe, portanto as classes personalizadas permitem capturar tipos específicos de erro sem capturar todos os erros.
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 usar withCallingHandlers
Use withCallingHandlers() quando quiser observar ou registrar condições sem interromper a execução. Use tryCatch() quando quiser se recuperar de uma condição e retornar um valor alternativo. Eles resolvem 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')A cadeia de sinalização de condições
Quando uma condição é sinalizada, R percorre a pilha de chamadas em busca de manipuladores. Os manipuladores de withCallingHandlers() são executados no contexto dinâmico, com a pilha de chamadas intacta. Os manipuladores de tryCatch() são executados depois que a pilha é desfeita — o contexto original desapareceu.
# 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()Implementação de suppressWarnings()
suppressWarnings(expr) é essencialmente withCallingHandlers(expr, warning = function(w) invokeRestart('muffleWarning')). Entender isso permite criar suas próprias variantes que suprimem apenas determinados tipos de aviso.
# 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ção rápida
Qual é a principal diferença entre withCallingHandlers() e tryCatch()?
Reinicializações: principais conclusões
Principais conclusões sobre withCallingHandlers e reinicializações:
withCallingHandlers()= manipulador local, pilha de chamadas intacta, a execução pode continuartryCatch()= saída não local, pilha desfeita, pode retornar um valor alternativoinvokeRestart('muffleWarning')suprime a exibição padrão do avisoinvokeRestart('muffleMessage')suprime a exibição padrão da mensagem- Use
withCallingHandlers()para coletar ou registrar todas as condições sem interromper - Classes de condição personalizadas permitem capturar seletivamente tipos específicos de erro
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')Perguntas Frequentes
A aula “withCallingHandlers() e reinicializações” é grátis?
Sim — o texto completo de “withCallingHandlers() e reinicializações” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de R Academy, atualize para CoddyKit PRO. O curso de R Academy inclui 4 aulas no total.
O que vou aprender em “withCallingHandlers() e reinicializações”?
Use withCallingHandlers() para o tratamento não local de condições. Você pratica R Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar R Academy?
Nenhuma experiência prévia é necessária. R Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “withCallingHandlers() e reinicializações”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de R Academy?
Sim. Cada aula de R Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Erros, avisos e mensagens em R
- tryCatch() para recuperação de erros
- withCallingHandlers() e reinicializações
- Escrevendo funções robustas com stop() e warning()