Search code examples
rmulticoreknitrfifomclapply

Knitr: redirect chunk code output to terminal


I want to monitor some pretty lengthy parallelized computations embedded in a knitr file.

The computations rely on a package I have written, and the relevant function uses mclapply from the multicore package for parallelization. This function outputs progress bars to monitor the progress of the computations using a slightly modified implementation of txtProgressBar from the utils package. The progress bar is printed to the terminal and updated through a fifo connection every time an iteration of mclapply is complete.

This works fine when sourcing from a file or calling directly the function, but I find no way to get this to work within knitr. I have tried the relevant chunk options, I can get messages and warnings redirected to the terminal, but not the progress bar. Can anyone help?

Sorry for not providing a minimal working example but I don't see how I could make one in this setting.


Solution

  • Because txtProgressBar() writes to stdout, and knitr captures everything in stdout, so currently it is not easy to show your progress bar if it is text-based and writes to stdout. Perhaps I can use evaluate::evaluate(debug = TRUE) internally to achieve what you want, but I'm not entirely sure if that works well with the text progress bar.

    My suggestions at the moment are:

    • use a GUI-based progress bar like tcltk::tkProgressBar()
    • write the progress to other places, e.g. (ab)using stderr

      ```{r progress}
      pb = txtProgressBar(min = 0, max = 100, file = stderr())
      for (i in 1:100) {
        setTxtProgressBar(pb, i)
        Sys.sleep(0.05)
      }
      close(pb)
      ```
      
    • or use your function outside a code chunk, e.g. in an inline expression (such as \Sexpr{my_multicore_function()} in Rnw or `r my_cool_fun()` in Rmd), because inline evaluation does not capture stdout