Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Text progress bar not showing up in Jupyter notebook #170

Open
imathews opened this issue Jun 10, 2024 · 4 comments
Open

Text progress bar not showing up in Jupyter notebook #170

imathews opened this issue Jun 10, 2024 · 4 comments
Labels
gui/Jupyter help wanted Extra attention is needed

Comments

@imathews
Copy link

I've been unable to get text progress bars (or really any progressr handler) to display within a Jupyter notebook. Given the following test case in a Jupyter environment, nothing displays when using progressr, though displays as expected if using utils::txtProgressBar. Both scenarios work just fine in RStudio.

library(progressr)
handlers('txtprogressbar')

test_slow_sum <- function(x) {
  # If we uncomment txtProgressBar lines, it works just as expected. But if we use progressr, nothing is displayed.
  # pb <- txtProgressBar(min = 0, max = length(x), initial = 0) 
  # p <- progressr::progressor(along = x)
  for (kk in seq_along(x)) {
    Sys.sleep(0.1)
    # setTxtProgressBar(pb,kk)
    # p(kk)
  }
}

with_progress(test_slow_sum(1:10))
Screen.Recording.2024-06-10.at.13.41.52.mov
@imathews imathews changed the title Text progress bar not showing up in jupyter notebook Text progress bar not showing up in Jupyter notebook Jun 10, 2024
@HenrikBengtsson
Copy link
Collaborator

Sounds like Jupyter Notebook handles output differently. I don't use it, so I haven't tested it there.

What happens if you use:

handlers(handler_txtprogressbar(file=stdout()))

?

@imathews
Copy link
Author

Unfortunately that doesn't seem to work either. I've put together a sample colab notebook to reproduce this easily (I'm fairly certain colab is using the same IRKernel as Jupyter under the hood to communicate with R, at the least we see the same behavior).

One other piece of information is that calling a simple cat("\r", val) within the for loop doesn't yield any output until the end, though if we add a flush.console() after cat(), we can see the output updated live.

I tried writing my own custom handler to leverage this behavior, though was unsuccessful - likely due to my limited knowledge here.

@nicolaschapados
Copy link

Adding my vote here. I'd really like this to work properly.

@HenrikBengtsson
Copy link
Collaborator

HenrikBengtsson commented Oct 16, 2024

I've looked more into this, and it's quite convoluted; Jupyter Notebook hacks utils::flush.console(). If we print(utils::flush.console) that function in vanilla R, we get:

> utils::flush.console
function () 
invisible(.Call(C_flushconsole))
<environment: namespace:utils>

by when doing so in Jupyter Notebook, we get:

function () 
{
    backup_env$utils_flush_console()
    flush_console()
}
<bytecode: 0x62b7266e87f0>
<environment: 0x62b726ea48b0>                 

After some more digging, that internal flush_console() is evaluate::flush_console(). I think that can be customized, and Jupyter Notebook customize it in ways I don't control. I don't think their hack can handle output to the standard error (stderr); it might be that it just swallows such output. Here's an example without progressr:

pbcon <- stderr()
pb <- utils::txtProgressBar(max = 100, file = pbcon)
for (value in c(0, 30, 40, 60, 80, 99)) {
  utils::setTxtProgressBar(pb, value = value)
  Sys.sleep(0.1)
}
cat("\n", file = pbcon)

That does not produce any progress output in the Jupyter Notebook GUI. If we switch to pbcon <- stdout(), we see the progress output.

So, a workaround is to output to have progressr output to stdout. Here is a proof of concept:

library(progressr)

## Force progressr bar even when running in non-interactive mode,
## e.g. interactive() is FALSE in Jupyter Notebook.
options(progressr.enable = TRUE)

## Jupyter Notebook hacks utils::flush.console(), but it appears
## to be incomplete and fail to handle output to the standard error
## (stderr), which is where we ideally would send progress output.
## Because of this limitation, we have to tell progressr to output
## to the standard output (stdout) instead.

handlers(handler_txtprogressbar(file = stdout()))

## For this to work, we also have to disable progressr's buffering
## of stdout
options(progressr.delay_stdout = FALSE)

## Test
progressr::with_progress({
  p <- progressor(10)
  for (value in 1:10) {
    p()
    Sys.sleep(1)
  }
})

I've confirmed that this works.

I think the best would be to see if there is an official Progress API for Jupyter Notebook and rely on that to report on progress, i.e. to create a handler_jupyter().

@HenrikBengtsson HenrikBengtsson added help wanted Extra attention is needed gui/Jupyter labels Oct 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gui/Jupyter help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants