Visão geral: Estou executando o knitr em um grande número de arquivos R/Markdown (na verdade, exercícios R/examssetTimeLimit()
para ser mais específico), alguns dos quais levam muito tempo para serem concluídos. Portanto, quero definir um limite de tempo para isso, que pode ser feito a partir do R base. No entanto, em algumas situações, isso pode levar a um arquivo não fechado sink()
; veja o exemplo reproduzível abaixo.
Pergunta: Posso fazer algo para evitar isso? É um bug no knitr
(ou em uma de suas dependências, como evaluate
)? Ou no R base?
Exemplo: configurei um arquivo mínimo timeout.Rmd
que calcula a resposta 42, espera 2 segundos e então o insere na saída do Markdown.
writeLines("
```{r}
ans <- 6 * 7
Sys.sleep(2)
```
Answer: `r ans`
", "timeout.Rmd")
Então, defini o limite de tempo para 1 segundo.
setTimeLimit(elapsed = 1)
Depois disso, a execução knitr
no timeout.Rmd
arquivo falha no {r}
trecho de código (como esperado):
knitr::knit("timeout.Rmd")
##
## processing file: timeout.Rmd
## |................................... | 67% [unnamed-chunk-1]
##
## Error in `remove_hooks()`:
## ! reached elapsed time limit
## Backtrace:
## ▆
## 1. ├─knitr::knit("timeout.Rmd")
## 2. │ └─knitr:::process_file(text, output)
## 3. │ ├─xfun:::handle_error(...)
## 4. │ ├─base::withCallingHandlers(...)
## 5. │ └─knitr:::process_group(group)
## 6. │ └─knitr:::call_block(x)
## 7. │ └─knitr:::block_exec(params)
## 8. │ └─knitr:::eng_r(options)
## 9. │ ├─knitr:::in_input_dir(...)
## 10. │ │ └─knitr:::in_dir(input_dir(), expr)
## 11. │ └─knitr (local) evaluate(...)
## 12. │ └─evaluate::evaluate(...)
## 13. │ └─evaluate (local) `<fn>`()
## 14. └─evaluate::remove_hooks(hook_list)
##
## Quitting from timeout.Rmd:2-5 [unnamed-chunk-1]
Depois dessa falha, tudo continua ok e podemos obter uma saída impressa como:
print(1)
## [1] 1
Mas depois de abrir um novo enredo como
plot(1)
não temos mais saída impressa
print(1)
porque agora existe uma abertura sink()
que captura toda a saída impressa. Somente após fechá-la, a impressão volta a funcionar
sink()
print(1)
## [1] 1
Consegui replicar esse problema em algumas máquinas Linux executando o R 4.5.0 ou 4.4.x diretamente no shell. (No RStudio, o tempo limite não parece ser detectado por algum motivo.)