Подтвердить что ты не робот

Можно ли отображать консольные сообщения (написанные "сообщением" ) в блестящем ui?

Я не очень хорошо понимаю сообщение R против кошки против печати против пр., Но мне интересно, возможно ли перехватывать сообщения и показывать их в блестящем приложении?

Пример: следующее приложение может захватывать операторы cat (и также печатать операторы), но не операторы сообщений

runApp(shinyApp(
  ui = fluidPage(
    textOutput("test")
  ),
  server = function(input,output, session) {
    output$test <- renderPrint({
      cat("test cat")
      message("test message")
    })
  }
))

Кросс-пост из группы Google "Блестящие обсуждения", так как я получил 0 ответов.

4b9b3361

Ответ 1

Yihui предложил использовать withCallingHandlers, и это действительно позволило мне решить. Я не был уверен, как использовать эту функцию таким образом, чтобы это было именно то, что мне нужно, потому что моя проблема заключалась в том, что у меня была функция, которая печатала несколько сообщений по одному за раз, и с использованием наивного подхода печаталось только последнее сообщение. Вот моя первая попытка (которая работает, если у вас есть только одно сообщение):

foo <- function() {
  message("one")
  message("two")
}

runApp(shinyApp(
  ui = fluidPage(
    actionButton("btn","Click me"),
    textOutput("text")
  ),
  server = function(input,output, session) {
    observeEvent(input$btn, {
      withCallingHandlers(
        foo(),
        message = function(m) output$text <- renderPrint(m$message)
      )
    })
  }
))

Обратите внимание, как выводится только two\n. Поэтому моим окончательным решением было использование функции html из пакета shinyjs (отказ от ответственности: я написал этот пакет), что позволяет мне изменять или добавлять к HTML внутри элемента. Он работал отлично - теперь оба сообщения были распечатаны в режиме реального времени.

foo <- function() {
  message("one")
  Sys.sleep(0.5)
  message("two")
}

runApp(shinyApp(
  ui = fluidPage(
    shinyjs::useShinyjs(),
    actionButton("btn","Click me"),
    textOutput("text")
  ),
  server = function(input,output, session) {
    observeEvent(input$btn, {
      withCallingHandlers({
        shinyjs::html("text", "")
        foo()
      },
        message = function(m) {
          shinyjs::html(id = "text", html = m$message, add = TRUE)
      })
    })
  }
))

Ответ 2

Я знаю, что это не так уж и изящно, но я немного поработал с использованием capture.output; К сожалению, sink не позволяет одновременно захватывать сообщения и выводить. Вы не получите их в исходном порядке, но вы можете извлечь оба потока по крайней мере (здесь обратился к HTML):

runApp(shinyApp(
  ui = fluidPage(
    uiOutput("test")
  ),
  server = function(input,output, session) {
    output$test <- renderUI({
      HTML(
      paste(capture.output(type = "message", expr = { 
        message(capture.output(type = "output", expr = {
          cat("test cat<br>")
          message("test message")
          cat("test cat2<br>")
          message("test message2")
        }))
      }), collapse="<br>")
  )})
 })
)

Вывод:

test message
test message2
test cat
test cat2

Возможно, в случае, если пользователь хочет захватить оба, но также и отделить их, это обеспечит удобную работу. (Ваш shinyjs пакет кажется опрятным, нужно взглянуть на него!)