r - rmarkdown::render() 输出到标准输出
问题描述
当我在 RStudio 中本地render()
创建*.Rmd
文件时,该render()
函数的输出显示在控制台中:
基本.Rmd
文件:
---
title: "test"
output: html_document
---
```{r setup, include=FALSE}
sink("./output.txt", type = 'output')
knitr::opts_chunk$set(echo = TRUE)
```
## Summary
```{r cars}
summary(cars)
```
## Error
```{r}
dbGetQuery()
```
构建:
library(rmarkdown)
render('./test.rmd')
输出:
当我在本地创建报告并且我可以看到进度和抛出的错误(如果有)时,这非常棒。我需要在 stdout(或 stderr)中监视此输出,但我无法将此输出接收到该位置,因为knitr
正在使用capture.input
which uses sink()
(见第一条评论)。我什至尝试下沉到一个文件,但是虽然output.txt
创建了文件,但该文件中没有任何记录。
这对我来说是个问题,因为我render()
在 Docker 容器中使用,我无法将.Rmd
Docker 容器中文件的块输出发送到 stderr 或 stdout。我需要监视.Rmd
文件内容器 R 代码中的块输出错误(以诊断连接数据库连接错误)并将这些块发送到 stdout 或 stderr 是唯一的方法(无需登录到容器,其中我的用例(即部署到 AWS)是不可能的)
我已经查看了knitr 块选项,似乎没有任何选项可以设置来强制块输出到文件或 stdout 或 stderr。
有什么方法可以将所有块输出写入render()
函数内部的 stdout 或 stderr 吗?这个几年前的问题与我的相似(如果不相同),但接受的答案不适合我的用例
解决方案
我会采取两种方法来解决这个问题 - 取决于你想要什么。
如果您想查看 stderr/stdout 输出,就像在控制台中一样,完成此操作的最简单方法是使用 shell 脚本来呈现您的文档,并将输出通过管道传输到文本。- 更小的包包含一个示例 shell 脚本render.r ,它对此非常有用。安装后littler
,并确保脚本在您的路径上可用,您可以运行:
render.r test.rmd > output.txt
或者
render.r test.rmd > output.txt 2>&1
在输出文件中包含 stderr。
但是,我发现此控制台输出通常不够详细,无法用于调试和故障排除。
因此,另一种选择是编辑 Rmd 文件以记录有关进度/错误的更多详细信息,并将记录器输出定向到外部文件。
这在云或 docker-container 计算环境的上下文中特别有用,因为可以将日志定向到允许实时日志记录和跨多个作业搜索日志的数据存储。就个人而言,我使用futile.logger包来执行此操作。
使用由futile.logger创建的记录器,这将按如下方式工作:
在您的 Rmd 文件或 Rmd 文件中的代码调用的函数中,将重要的错误和警告消息重定向到记录器。做到这一点的最佳方法是另一个问题的主题,根据我的经验,任务因任务而异。
- 至少,这会导致在您的 Rmd 文件中插入一系列 R 命令,如下所示:
可能编辑记录的消息以提供更多上下文。library(futile.logger) flog.info('Querying data .. ') data <- tryCatch(dbGetQuery(...), warning = function(war) {flog.warn(war)}, error = function(err) {flog.error(err)}, ...)
- 更彻底的解决方案将全局应用于代码块或文件。我没有在 Rmd 的上下文中亲自对此进行过测试,但它可能涉及使用
withCallingHandlers
或更改options(error = custom_logging_function)
.
- 至少,这会导致在您的 Rmd 文件中插入一系列 R 命令,如下所示:
在您的 R session中,在渲染 Rmd 之前,将记录器输出重定向到文件或您想要的目的地。
- 这看起来像:
library(futile.logger) flog.logger(name = 'ROOT', appender = appender.file('render.log')) rmarkdown::render('my_document.Rmd')
- 这看起来像:
在呈现文档时,您将看到记录器输出打印到
render.log
文件中。
我会注意到,虽然我积极使用该futile.logger
包,但该包现在已被弃用为它的新迭代,称为logger。我没有专门尝试过这种方法logger
,但我怀疑如果不是更好的话,它也会同样有效。logger docs 的这篇关于迁移的小插图很好地描述了 logger 和 futile.logger 之间的区别。
推荐阅读
- r - 将数字添加到 R 中列表内的向量
- python - django 中未解决的导入“博客”
- javascript - 有没有人在 PhoneGap 构建中使用过 OneSignal sendtag?
- java - 麻烦正确使用布尔方法以及使用递归方法
- r - 具有置换 p 值的自举 t 检验
- django - 如何使用 msg.send() 在 django 的 html 电子邮件模板中传递用户名
- php - 在 Woocommerce 3.5 中将付款方式标题添加到管理订单列表
- c# - C# MySQLDataReader 为所有行返回相同的字符串
- excel - 保持行连接到单独工作表上的链接列
- loopbackjs - 如何在控制器方法中注入请求级上下文