0

I am writing a graphical wrapper for a (heavy) external program. I want my Shiny program to pause while the program is running; the only thing to be updated should be what the external program sends to stdout and stderr. Is it possible?

Technically, I am calling the external program with processx::run(...), which is similar to system(..., wait=T). I do not want to run the external program in the background, such as when using system(..., wait=F)

I am diverting stdout (and stderr) to a log file, so I tried using a reactiveFileReader to display that file on the screen. However, this way does not work, as reactivity is paused when running the external program.

Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
Sam
  • 127
  • 10
  • Crossposted from the shiny community forum https://community.rstudio.com/t/how-does-one-show-stdout-of-an-external-program/113006/3 (no answer received). – Sam Aug 23 '21 at 09:20

2 Answers2

1

Unless you allow a second thread to run (which is effectively what wait=F does), it is not possible, for the simple reason that all execution and event processing stops while the program waits for your process to complete. The next event will only process when your program is done, including reacting to log file changes.

As an alternative, you can suspend reactivity of all components except the log output, and then resume once your program is done running.

0

I think have found a solution (not too elegant). I can create a separate shiny program that would only output the log file, saved in a specific location. This shiny program can be displayed in an iframe.

I have found that an iframe inside a Shiny app can be refreshed even though the application itself waits for system(wait=T) to finish.

You can verify the above statement for yourself with the code below. The code for insterting an iframe to a shiny app is taken from SO

library(shiny)


ui <- fluidPage(titlePanel("Getting Iframe"), 
               sidebarLayout(
                 sidebarPanel(
                   sliderInput("mySlider", "# of observations", 1, 1000, value=500),
                   plotOutput("myPlot"),
                   actionButton("sleepBtn", "Sleep"),
                   ),
                 mainPanel(fluidRow(
                   htmlOutput("frame")
                 )
                 )
               ))

server <- function(input, output) {
 output$frame <- renderUI({
   my_test <- tags$iframe(src="http://news.scibite.com/scibites/news.html", height=600, width=535)
   print(my_test)
   my_test
 })
 output$myPlot <- renderPlot({ hist(rnorm(input$mySlider)) })
 observeEvent(input$sleepBtn, {
   system("sleep 60", wait=T)
   
 })
}

shinyApp(ui, server)
Sam
  • 127
  • 10