Ответ 1
Чтобы выйти из процесса вязания рано, вы можете использовать функцию knitr::knit_exit()
в любом месте исходного документа (в фрагменте кода или встроенном выражении). Когда вызывается knit_exit()
, knitr будет игнорировать всю оставшуюся часть документа и выписать результаты, которые он собрал до сих пор.
В настоящий момент нельзя допускать ошибки в встроенном R-коде. Вы должны убедиться, что встроенный R-код всегда работает без ошибок 1. Если ошибки происходят, вы должны увидеть диапазон строк, которые вызвали ошибку из журнала knitr в консоли, формы Quitting from lines x1-x2 (filename.Rmd)
. Затем вы можете перейти к файлу filename.Rmd
и посмотреть, что не так с линиями от x1
до x2
. То же самое относится к фрагментам кода с опцией chunk error = FALSE
.
Помимо описанных выше типов ошибок, может оказаться сложным найти источник проблемы. Например, когда вы непреднамеренно unlink()
текущий каталог, он не должен останавливать процесс вязания, потому что unlink()
преуспел в любом случае. Вы можете столкнуться с проблемами после процесса вязания, например, LaTeX/HTML не может найти файлы выходных фигур. В этом случае вы можете попробовать применить knit_exit()
ко всем фрагментам кода в документе один за другим. Один из способов добиться этого - настроить кусок для запуска knit_exit()
после определенного фрагмента. Ниже приведен пример использования линейного поиска (вы можете улучшить его, используя вместо этого bisection):
#' 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
}
}
}
- Это по дизайну. Я думаю, что неплохо иметь
error = TRUE
для фрагментов кода, поскольку иногда мы хотим показывать ошибки, например, для целей обучения. Однако, если я допускаю ошибки для встроенного кода, авторы могут не распознать фатальные ошибки во встроенном коде. Встроенный код обычно используется для встраивания значений inline, и я не думаю, что это имеет смысл, если встроенное значение является ошибкой. Представьте предложение в отчете, напримерThe P-value of my test is ERROR
, и если knitr не сообщит об ошибке, авторы потребуют очень внимательно прочитать отчет, чтобы определить эту проблему. Я думаю, что плохая идея - полагаться на человеческие глаза, чтобы найти такие ошибки.