0Pricing
R Academy · Aula

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 continuar
  • tryCatch() = saída não local, pilha desfeita, pode retornar um valor alternativo
  • invokeRestart('muffleWarning') suprime a exibição padrão do aviso
  • invokeRestart('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

  1. Erros, avisos e mensagens em R
  2. tryCatch() para recuperação de erros
  3. withCallingHandlers() e reinicializações
  4. Escrevendo funções robustas com stop() e warning()
← Voltar para R Academy