quarto-dev / quarto-cli

Open-source scientific and technical publishing system built on Pandoc.
https://quarto.org
Other
3.99k stars 328 forks source link

Capture stderr with knitr engine like to match Jupyter engine output #10503

Open hadley opened 3 months ago

hadley commented 3 months ago

Render this doc. Where does the message go?

```{r}
cat("Hi!", file = stderr())
hadley commented 3 months ago

Maybe this only doesn't work in RStudio?

hadley commented 3 months ago

Now I can see it 😭

cscheid commented 3 months ago

For what's worth, I don't see any output when I try to repro this myself:

---
keep-md: true
---
```{r}
cat("Hi!", file = stderr())

The `keep-md` output is:

keep-md: true

::: {.cell}

cat("Hi!", file = stderr())

:::



I'm not sure this is a bug or not (or what's the expected knitr behavior), but I can reproduce the "where's the output" confusion.
cderv commented 3 months ago

The stderr() goes into same place at what is logged by knitr as progress.

==> quarto preview test2.qmd --to default --no-watch-inputs --no-browse

++ Activating rlang global_entrace

processing file: test2.qmd
  |...................................                 |  67% [unnamed-chunk-1]
Hi!

output file: test2.knit.md

pandoc 
  to: html
  output-file: test2.html
  standalone: true
  section-divs: true
  html-math-method: mathjax
  wrap: none
  default-image-extension: png

metadata
  document-css: false
  link-citations: true
  date-format: long
  lang: en
  title: test

Output created: test2.html

Watching files for changes
Browse at http://localhost:4877/

I don't think knitr does anything specific and it is at the evaluate layer, where stderr() is used to log things.

@hadley when you said you could see it, is this now in the expected part ?

@cscheid don't you see the Hi! in the progress message we show while rendering ?

cscheid commented 3 months ago

Ah, yes. This is what I see (and you'll see why I missed it)

image
cscheid commented 3 months ago

I think we could be doing better than just printing to stderr; I'm not sure how to standardize this across engines, but my feeling is that this output should end up in the document by default.

cderv commented 3 months ago

I think we could be doing better than just printing to stderr;

You mean quarto showing the knitr logging in red as stderr ?

this output should end up in the document by default.

You mean the Hi! from cat("Hi!", file = stderr()) ? This code explicitly print to stderr(). Using stdout() will go in document as it will be catched by evaluate. But using stderr(), evaluate::evaluate() does not handle it in a special manner, and it is sent to stderr(), as other type of logging if you ask for it.

> evaluate::evaluate('cat("Hi!\n", file = stderr())')
Hi!
<evaluation>
Source code:
  cat("Hi!
  ", file = stderr())
> evaluate::evaluate('cat("Hi!\n", file = stderr())', log_echo = TRUE)
cat("Hi!
", file = stderr())

Hi!
<evaluation>
Source code:
  cat("Hi!
  ", file = stderr())

Not something we can really change at quarto level IMO. We have this behavior for knitr and evaluate itself.

cscheid commented 3 months ago

My point is that having stderr end up not at the document is a problem, because

---
format: html
---

```{python}
import sys
print("Hi!", file=sys.stderr)


<img width="693" alt="image" src="https://github.com/user-attachments/assets/94eb43bb-ae37-4b06-a6cc-ff12b463c097">
hadley commented 3 months ago

Yeah, the problem is that I forgot the \n, so my output ended muddled up in the progress bar.

I do think it's correct to not capture stderr() because that gives you some standard way to escape knitr's capture and emit text into the log.

cscheid commented 3 months ago

@hadley So, aside from the increasing the visibility of the output, you don't think there's a bug here? Hm.

This works entirely differently in Jupyter, and I think the Jupyter behavior is less bad. I think printing into the log should require a more explicit API call...

hadley commented 3 months ago

@cscheid it's possible that the jupyter way is the right way here, but if you change this behaviour in quarto, it's going to mess up a LOT of existing logging code from Rmds.

cscheid commented 3 months ago

Noted.

I wonder if the best solution here is to add an option to both sides, and have different defaults for different engines. We already have some settings where jupyter behaves differently from knitr...

hadley commented 3 months ago

It's not currently possible to capture stderr in evaluate so I think it would be hard to implement currently, but that's definitely something I could add.

cscheid commented 3 months ago

It's not high priority - maybe something I can try at the 2026 dev day...