Получение сообщений об ошибках из r, отображаемых в том виде, в каком они изначально появляются в сеансе r, с помощью knitr

Я хотел бы создать html-документ с помощью Rmarkdown, в котором могут отображаться сообщения об ошибках из R, поскольку они изначально появляются в интерактивном сеансе R.

Этот вопрос аналогичен, но не требует, чтобы сообщения об ошибках отображались точно так же, как в интерактивном сеансе: я попытался использовать error=TRUE для данного фрагмента, при этом ошибка получает префикс Error in eval(expr, envir, enclos)::

Со следующим фрагментом:

```{r, error=TRUE}
notexistingvariable
```

Я ожидаю:

Error: object 'notexistingvariable' not found

Я получил:

Error in eval(expr, envir, enclos): object 'notexistingvariable' not found

Я пробовал добавить опцию results="asis", но здесь это не повлияло. Я думаю, это относится только к выводу без ошибок.


Попытка использовать wrap.error

Как предложил в ответах, я попытался установить пользовательскую функцию wrap.error.

test.Rmd:

---
title: "test"
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)

wrap.error <- function(x, options) {
  # x is an error object, with components "call" and "message".  Ignore
  # the call, but wrap the result like code:
  paste0("```\n## Error: ", x$message, "\n```")
}
```

```{r, error=TRUE}
notexistingvariable
```

Конвертация в html:

$ R -e "rmarkdown::render('test.Rmd',output_file='test.html')"

R version 3.5.1 (2018-07-02) -- "Feather Spray"
Copyright (C) 2018 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

> rmarkdown::render('test.Rmd',output_file='test.html')


processing file: test.Rmd
  |................                                                 |  25%
  ordinary text without R code

  |................................                                 |  50%
label: setup (with options) 
List of 1
 $ include: logi FALSE

  |.................................................                |  75%
  ordinary text without R code

  |.................................................................| 100%
label: unnamed-chunk-1 (with options) 
List of 1
 $ error: logi TRUE


output file: test.knit.md

/usr/bin/pandoc +RTS -K512m -RTS test.utf8.md --to html4 --from markdown+autolink_bare_uris+ascii_identifiers+tex_math_single_backslash --output test.html --smart --email-obfuscation none --self-contained --standalone --section-divs --template /home/bli/R/x86_64-pc-linux-gnu-library/3.5/rmarkdown/rmd/h/default.html --no-highlight --variable highlightjs=1 --variable 'theme:bootstrap' --include-in-header /tmp/RtmpAoBtc7/rmarkdown-str53186fa5c04d.html --mathjax --variable 'mathjax-url:https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML' 

Output created: test.html
> 
> 

Файл test.html выглядит следующим образом:

html rendering by firefox


Использование wrap.simpleError, как теперь предлагает обновленный ответ, работает.

1
0
540
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

(Обновлено, чтобы отразить изменения R 3.5.x)

Вы можете установить собственные рендереры для вывода (см. vignette("knit_print")), но я думаю, что они не вызываются при возникновении ошибки. В этом случае вызывается универсальная функция wrap(). knitr определяет метод wrap.error() и до R 3.5.0, который может быть переопределен пользователем. Однако в последней версии R методы, определенные в пакете, выбираются вместо методов, определенных пользователем, поэтому он больше не работает.

Однако решение некоторых ошибок все же есть. В примере в вопросе созданный объект ошибки имеет класс c("simpleError", "error", "condition"), а knitr не определяет метод wrap.simpleError(). Вы можете определить один и переопределить его обработку.

Вы делаете это так:

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)

wrap.simpleError <- function(x, options) {
  # x is an error object, with components "call" and "message".  Ignore
  # the call, but wrap the result like code:
  paste0("```\n## Error: ", x$message, "\n```")
}
```

```{r, error=TRUE}
notexistingvariable
```

Результат будет примерно таким: enter image description here

Также есть ловушка вывода для обработки ошибок: см. https://yihui.name/knitr/hooks/. Однако, похоже, он вызывается после wrap.error, когда сообщение уже сформировано. Вы можете отредактировать это сообщение, чтобы удалить части, которые вы не хотите использовать в таком коде:

```{r}   
knitr::knit_hooks$set(error = function(x, options) {
  paste0("```\n", 
         sub(" in eval(expr, envir, enclos)", "", x, fixed = TRUE),
         "\n```")
})
```e

Это может быть более надежным, чем подход wrap.simpleError, который перестанет работать, если knitr когда-либо определит такой метод wrap.simpleError. Он также будет обрабатывать все ошибки, а не только ошибки "simpleError". Он имеет Недостатком является то, что его, вероятно, сложнее настроить для обработки различных типов ошибок, и он может не работать в разных регионах, где «Ошибка в» переведена на какой-либо другой язык.

По какой-то причине это не влияет на мой документ. Я также пробовал использовать минимальный документ Rmakrdown, но все еще получаю eval(expr, envir, enclos) в сообщении об ошибке.

bli 11.09.2018 18:45

У меня это работает в knitr 1.20. Вы пользуетесь этой версией?

user2554330 11.09.2018 20:36

У меня тоже версия 1.20. А я использую R 3.5.1. Я даже попытался включить вызов sub вокруг x$message, но безуспешно. Подозреваю, что wrap.error не используется. Я обновлю свой первоначальный вопрос.

bli 12.09.2018 11:39

Я использовал R 3.4.4, и все изменилось в R 3.5.1. Я обновил ответ.

user2554330 12.09.2018 12:58

Другие вопросы по теме