编织Rmd文档时如何请求提前退出? [英] How to request an early exit when knitting an Rmd document?

查看:47
本文介绍了编织Rmd文档时如何请求提前退出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设您有一个R markdown文档,它将无法清晰呈现.

Let's say you have an R markdown document that will not render cleanly.

我知道您可以将knitr块选项error设置为TRUE,以请求继续进行评估,即使存在错误也是如此.您可以通过error = TRUE为单个块执行此操作,或者通过knitr::opts_chunk$set(error = TRUE)以更全局的方式进行操作.

I know you can set the knitr chunk option error to TRUE to request that evaluation continue, even in the presence of errors. You can do this for an individual chunk via error = TRUE or in a more global way via knitr::opts_chunk$set(error = TRUE).

但是有时仍然存在错误,这些错误仍然对编织过程致命.我最近遇到的两个示例:尝试unlink()当前工作目录(哎呀!),以及当RStudio不可用时从内联R代码调用rstudioapi::getVersion().是否有对这类错误(即error = TRUE所不能及的错误)的一般描述?有没有办法容忍内联R代码和块中的错误?

But sometimes there are errors that are still fatal to the knitting process. Two examples I've recently encountered: trying to unlink() the current working directory (oops!) and calling rstudioapi::getVersion() from inline R code when RStudio is not available. Is there a general description of these sorts of errors, i.e. the ones beyond the reach of error = TRUE? Is there a way to tolerate errors in inline R code vs in chunks?

在这种情况下,还有更多官方方法可以提前停止编织或自动调试吗?

Also, are there more official ways to halt knitting early or to automate debugging in this situation?

推荐答案

要尽早退出编织过程,可以在源文档中的任何位置(代码块或内联表达式)使用函数knitr::knit_exit().调用knit_exit()后,编织器将忽略文档的所有其余部分,并写出到目前为止收集的结果.

To exit early from the knitting process, you may use the function knitr::knit_exit() anywhere in the source document (in a code chunk or inline expression). Once knit_exit() is called, knitr will ignore all the rest of the document and write out the results it has collected so far.

目前尚无办法容忍内联R代码中的错误.您需要确保内联R代码始终运行没有错误 1 .如果确实发生错误,您应该在控制台中的 knitr 日志中看到产生错误的行的范围,格式为Quitting from lines x1-x2 (filename.Rmd).然后,您可以转到文件filename.Rmd,查看从x1x2的行出了什么问题.相同的情况也适用于带有块选项error = FALSE的代码块.

There is no way to tolerate errors in inline R code at the moment. You need to make sure inline R code always runs without errors1. If errors do occur, you should see the range of lines that produced the error from the knitr log in the console, of the form Quitting from lines x1-x2 (filename.Rmd). Then you can go to the file filename.Rmd and see what is wrong with the lines from x1 to x2. Same thing applies to code chunks with the chunk option error = FALSE.

除了上面提到的错误类型之外,查找问题根源可能很棘手.例如,当您无意中unlink()当前目录时,它不应停止编织过程,因为unlink()仍然成功.在编织过程之后,您可能会遇到问题,例如LaTeX/HTML无法找到输出图形文件.在这种情况下,您可以尝试将knit_exit()应用于文档中的所有代码块.实现此目的的一种方法是设置一个块挂钩,以在某个特定块之后运行knit_exit().以下是使用线性搜索的示例(您可以改为使用二分法来改进它):

Beyond the types of errors mentioned above, it may be tricky to find the source of the problem. For example, when you unintentionally unlink() the current directory, it should not stop the knitting process, because unlink() succeeded anyway. You may run into problems after the knitting process, e.g., LaTeX/HTML cannot find the output figure files. In this case, you can try to apply knit_exit() to all code chunks in the document one by one. One way to achieve this is to set up a chunk hook to run knit_exit() after a certain chunk. Below is an example of using linear search (you can improve it by using bisection instead):

#' Render an input document chunk by chunk until an error occurs
#' 
#' @param input the input filename (an Rmd file in this example)
#' @param compile a function to compile the input file, e.g. knitr::knit, or
#'   rmarkdown::render
knit_debug = function(input, compile = knitr::knit) {
  library(knitr)
  lines = readLines(input)
  chunk = grep(all_patterns$md$chunk.begin, lines)  # line number of chunk headers

  knit_hooks$set(debug = function(before) {
    if (!before) {
      chunk_current <<- chunk_current + 1
      if (chunk_current >= chunk_num) knit_exit()
    }
  })

  opts_chunk$set(debug = TRUE)

  # try to exit after the i-th chunk and see which chunk introduced the error
  for (chunk_num in seq_along(chunk)) {
    chunk_current = 0  # a chunk counter, incremented after each chunk
    res = try(compile(input))
    if (inherits(res, 'try-error')) {
      message('The first error came from line ', chunk[chunk_num])
      break
    }
  }
}


  1. 这是设计使然.我认为对代码块使用error = TRUE是个好主意,因为有时我们想要显示错误,例如,出于教学目的.但是,如果我也允许内联代码出错,那么作者可能无法识别内联代码中的致命错误.内联代码通常用于嵌入 values 内联,如果内联值是错误,我认为这没有多大意义.想象一下像The P-value of my test is ERROR这样的报告中的一个句子,如果 knitr 没有发出错误信号,它将要求作者非常仔细地阅读报告输出以发现此问题.我认为必须依靠人眼才能发现这种错误是一个坏主意.
  1. This is by design. I think it is a good idea to have error = TRUE for code chunks, since sometimes we want to show errors, for example, for teaching purposes. However, if I allow errors for inline code as well, authors may fail to recognize fatal errors in the inline code. Inline code is normally used to embed values inline, and I don't think it makes much sense if an inline value is an error. Imagine a sentence in a report like The P-value of my test is ERROR, and if knitr didn't signal the error, it will require the authors to read the report output very carefully to spot this issue. I think it is a bad idea to have to rely on human eyes to find such mistakes.

这篇关于编织Rmd文档时如何请求提前退出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆