Knitr:将块码输出重定向到终端

时间:2021-09-30 06:14:08

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

我想监视嵌入在knitr文件中的一些非常冗长的并行计算。

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.

计算依赖于我编写的包,相关函数使用多核包中的mclapply进行并行化。此函数使用utils包中稍微修改的txtProgressBar实现输出进度条以监视计算的进度。每当mclapply的迭代完成时,进度条将打印到终端并通过fifo连接进行更新。

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?

当从文件中获取或直接调用该函数时,这样可以正常工作,但我发现无法在knitr中使用它。我已经尝试了相关的块选项,我可以将消息和警告重定向到终端,但不是进度条。有人可以帮忙吗?

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

很抱歉没有提供最小的工作示例,但我不知道如何在此设置中制作一个。

2 个解决方案

#1


6  

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.

由于txtProgressBar()写到标准输出,并knitr捕获标准输出的一切,所以目前它是不容易表现出你的进度条,如果它是基于文本的,并写入到标准输出。也许我可以在内部使用evaluate :: evaluate(debug = TRUE)来实现你想要的,但我不完全确定它是否适用于文本进度条。

My suggestions at the moment are:

我目前的建议是:

  • use a GUI-based progress bar like tcltk::tkProgressBar()
  • 使用基于GUI的进度条,如tcltk :: tkProgressBar()

  • write the progress to other places, e.g. (ab)using stderr

    将进度写入其他地方,例如(ab)使用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

    或者在代码块之外使用你的功能,例如在内联表达式中(例如Rnw中的\ Sexpr {my_multicore_function()}或Rmd中的`r my_cool_fun()`),因为内联评估不捕获stdout

#2


1  

Having read the point about printing progress bar to stderr in Yihui's answer I would suggest temporary redirecting stdout to stderr with sink().

在Yihui的回答中读到有关打印进度条的问题后,我建议暂时将stdout重定向到带有sink()的stderr。

sink(stderr())

your_code()

sink()

#1


6  

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.

由于txtProgressBar()写到标准输出,并knitr捕获标准输出的一切,所以目前它是不容易表现出你的进度条,如果它是基于文本的,并写入到标准输出。也许我可以在内部使用evaluate :: evaluate(debug = TRUE)来实现你想要的,但我不完全确定它是否适用于文本进度条。

My suggestions at the moment are:

我目前的建议是:

  • use a GUI-based progress bar like tcltk::tkProgressBar()
  • 使用基于GUI的进度条,如tcltk :: tkProgressBar()

  • write the progress to other places, e.g. (ab)using stderr

    将进度写入其他地方,例如(ab)使用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

    或者在代码块之外使用你的功能,例如在内联表达式中(例如Rnw中的\ Sexpr {my_multicore_function()}或Rmd中的`r my_cool_fun()`),因为内联评估不捕获stdout

#2


1  

Having read the point about printing progress bar to stderr in Yihui's answer I would suggest temporary redirecting stdout to stderr with sink().

在Yihui的回答中读到有关打印进度条的问题后,我建议暂时将stdout重定向到带有sink()的stderr。

sink(stderr())

your_code()

sink()