【问题标题】:Knitr: redirect chunk code output to terminalKnitr:将块代码输出重定向到终端
【发布时间】:2013-11-29 07:44:43
【问题描述】:

我想监控嵌入在 knitr 文件中的一些相当冗长的并行计算。

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

这在从文件中获取或直接调用函数时工作正常,但我找不到让它在 knitr 中工作的方法。我已经尝试了相关的块选项,我可以将消息和警告重定向到终端,但不能重定向到进度条。任何人都可以帮忙吗?

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

【问题讨论】:

    标签: r multicore knitr fifo mclapply


    【解决方案1】:

    在阅读了 Yihui 的回答中关于将进度条打印到 stderr 的观点后,我建议将 stdout 临时重定向到 stderrsink()

    sink(stderr())
    
    your_code()
    
    sink()
    

    【讨论】:

    • 这在您无法控制进度条的发送位置时很有帮助(例如,如果使用其他人的包,如 rstan
    【解决方案2】:

    因为txtProgressBar() 写入stdout,而knitr 捕获stdout 中的所有内容,所以目前如果它是基于文本的并写入stdout,则显示进度条并不容易。也许我可以在内部使用evaluate::evaluate(debug = TRUE) 来实现您想要的,但我不完全确定这是否适用于文本进度条。

    我目前的建议是:

    • 使用基于 GUI 的进度条,例如 tcltk::tkProgressBar()
    • 将进度写入其他地方,例如(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)
      ```
      
    • 或者在代码块之外使用你的函数,例如在内联表达式中(例如 Rnw 中的 \Sexpr{my_multicore_function()} 或 Rmd 中的 `r my_cool_fun()`),因为内联评估不会捕获标准输出

    【讨论】:

    • 感谢@Yihui 的回复,希望你能光临!我会按照你的第一个建议尝试一些事情,第二个建议意味着失去缓存计算的能力。抛开多核问题不谈,你知道有什么方法可以监控块内进行的计算状态吗?
    • 或许你可以把进度写到其他地方,比如在一个文件里:txtProgressBar(..., file = 'progress_temp.txt')。或将其写入标准错误。我会更新我的答案。
    • 感谢StdErr() hack,它易于实现并且创造了奇迹。虽然我在使用它,但感谢 knitr,它是我每天使用的一个很棒的工具。
    • @Yihui 有没有办法让 knitr 不捕获标准输出?我想运行 knitr 文档,但是当出现问题时,我看不到任何调试消息、警告、..
    • @YihuiXie "knitr 捕获标准输出中的所有内容" 据我所知,print(1+1) 是这样,但1+1 不是这样。在这种情况下,HTML 或 PDF 中没有任何输出。当然,如果在 python 控制台(2.7)中运行1+1,则会有输出。这是knitr的正常行为还是我做错了什么?
    猜你喜欢
    • 2022-11-11
    • 2017-12-01
    • 1970-01-01
    • 2012-10-29
    • 2017-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多