nil*_*ole 6 shell r stream command-line-interface shiny
如何捕获正在进行的system()操作的输出并将其“实时”传输到 Shiny 前端?
intern=T 在字符向量中捕获整个输出,但我更喜欢“听”系统输出。
library(shiny)
ui <- fluidPage(
titlePanel("Stream the system output"),
sidebarLayout(
sidebarPanel(
actionButton("btn1",label = "Let's stream")
),
mainPanel(
textOutput("textstream_output")
)
)
)
server <- function(input, output, session) {
rv <- reactiveValues("textstream"=c(""))
output$textstream_output <- renderText({
rv$textstream
})
observeEvent(input$btn1,{
# problem: is evaluated after finish, not during operation
rv$textstream <- system("Rscript -e \"for(i in 1:5){ print(Sys.time()); Sys.sleep(1); };\"",
intern = T)
})
}
shinyApp(ui = ui, server = server)
Run Code Online (Sandbox Code Playgroud)
使用 运行system命令时intern=F,R 控制台每秒持续更新一次。我怎样才能在 Shiny 中建立它,理想情况下不必将system调用分成更小的块?
可能相关:
reactiveTimer提供一种方法。我的猜测是您的方法不起作用,因为observeEvent只有在表达式评估完成后才更新反应对象。这是我的方法。我创建了一个要在后台运行的脚本,so_script.R并将输出转移到so_output.txt. 我们希望so_output.txt在脚本运行时查看内容。
cat('sink(file = "so_output.txt")
for (i in 1:10) {
cat(format(Sys.time(), format = "%H:%M:%S"), "\n")
Sys.sleep(1)
}
cat("*** EOF ***\n")
sink()
', file = "so_script.R")
Run Code Online (Sandbox Code Playgroud)
这是闪亮的应用程序:
library(shiny)
ui <- fluidPage(
titlePanel("Stream the system output"),
sidebarLayout(
sidebarPanel(
actionButton("btn_start",label = "Let's stream"),
actionButton("btn_stop",label = "Stop")
),
mainPanel(
htmlOutput("textstream_output")
)
)
)
server <- function(input, output, session) {
rv <- reactiveValues(textstream = c(""),
timer = reactiveTimer(1000),
started = FALSE)
observeEvent(input$btn_start, {
rv$started <- TRUE
system2("Rscript", "so_script.R", wait = FALSE)
})
observeEvent(input$btn_stop, { rv$started <- FALSE })
observe({
rv$timer()
if (isolate(rv$started))
rv$textstream <- paste(readLines("so_output.txt"), collapse = "<br/>")
})
output$textstream_output <- renderUI({
HTML(rv$textstream)
})
}
shinyApp(ui = ui, server = server)
Run Code Online (Sandbox Code Playgroud)
每次定时器触发时,我们都会读入so_output.txtif 流媒体已经开始的内容。输出: