异步进程阻止R Shiny应用程序 [英] Async process blocking R Shiny app

查看:90
本文介绍了异步进程阻止R Shiny应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

应该可以使用R包futurepromises通过Shiny应用程序触发异步(长时间运行)处理,而无需在异步进程在另一个R进程中运行时冻结应用程序的其余部分.

请参阅:

https://cran.r-project.org/web/packages/promises/vignettes/intro.html
https://cran.r-project.org/web/packages/promises/vignettes/overview.html
https://cran.r-project.org/web/packages/promises/vignettes/futures.html
https://cran.r-project.org/web/packages/promises/vignettes/shiny.html

我使它可以在基于R脚本的环境中工作,但是当我实现一个具有2个功能的简单闪亮应用程序时,却无法使它工作.运行异步功能时,始终会阻止非异步"功能,但事实并非如此.

我已经在软件包promises的GitHub存储库上发布了相同的问题: https://github.com/rstudio/promises/issues/23

我也将其张贴在这里,希望有人能提供帮助.

问题是:

  1. 您能否看一下下面发布的闪亮应用程序示例,并让我知道为什么异步处理阻止了该应用程序? (它不应阻止).
  2. 理想情况下,您能否提供一个具有无阻塞异步和正常功能(在异步运行时可以访问)的应用程序的小示例?

环境

Mac OS 10.12

$ R --version
R version 3.4.3 (2017-11-30) -- "Kite-Eating Tree"

remove.packages("future")
remove.packages("promises")
remove.packages("shiny")

install.packages("future")
install.packages("devtools")
devtools::install_github("rstudio/promises")
devtools::install_github("rstudio/shiny")

> packageVersion("future")
[1] ‘1.8.1’
> packageVersion("promises")
[1] ‘1.0.1’
> packageVersion("shiny")
[1] ‘1.0.5.9000’

关于闪亮软件包版本的一个侧面问题, https://rstudio.github.io/promises/articles/intro.html 表示应为> = 1.1,但即使使用devtools进行安装,该版本仍为1.0.5 ....这是一个问题还是文档中有错字?

首先,您可以将promises与Shiny输出配合使用.如果您使用的是异步兼容版本的Shiny(版本> = 1.1),则所有内置的renderXXX函数都可以处理常规值或promise.

问题示例

我已经实现了一个简单的闪亮应用程序,该应用程序受上述URL上的示例启发. 闪亮的应用程序具有2个部分":

  1. 触发长期运行"异步处理的按钮.这可以通过功能read_csv_async进行模拟,该功能休眠数秒,然后将csv文件读取到数据帧中.然后,将df呈现在按钮下方.
  2. 一个简单的功能应在任何时候都可以使用(包括异步处理触发时):它包含一个滑块,该滑块定义了要生成的多个随机值.然后,我们绘制这些值的直方图.

问题是在进行异步处理时,第二个功能(直方图更新)被阻止了.

global.R

library("shiny")
library("promises")
library("dplyr")
library("future")

# path containing all files, including ui.R and server.R
setwd("/path/to/my/shiny/app/dir")   

plan(multiprocess)

# A function to simulate a long running process
read_csv_async = function(sleep, path){
      log_path = "./mylog.log"
      pid = Sys.getpid()
      write(x = paste(format(Sys.time(), "%Y-%m-%d %H:%M:%OS"), "pid:", pid, "Async process started"), file = log_path, append = TRUE)
      Sys.sleep(sleep)
      df = read.csv(path)
      write(x = paste(format(Sys.time(), "%Y-%m-%d %H:%M:%OS"), "pid:", pid, "Async process work completed\n"), file = log_path, append = TRUE)
      df
}

ui.R

fluidPage(
  actionButton(inputId = "submit_and_retrieve", label = "Submit short async analysis"),
  br(),
  br(),
  tableOutput("user_content"),

  br(),
  br(),
  br(),
  hr(),

  sliderInput(inputId = "hist_slider_val",
              label = "Histogram slider",
              value = 25, 
              min = 1,
              max = 100),

  plotOutput("userHist")
)

server.R

function(input, output){
    # When button is clicked
    # load csv asynchronously and render table
    data_promise = eventReactive(input$submit_and_retrieve, {
        future({ read_csv_async(10, "./data.csv") }) 
    })
   output$user_content <- renderTable({
     data_promise() %...>% head(5)
    })


  # Render a new histogram 
  # every time the slider is moved
  output$userHist = renderPlot({
    hist(rnorm(input$hist_slider_val))
  })
}

data.csv

Column1,Column2
foo,2
bar,5
baz,0

谢谢!

解决方案

所以,此行为是正常现象,请参见

该软件包的作者提到不支持此功能,如果有足够的人要求,可以添加该功能.如果您正在寻找此信息,请转至GitHub问题,就像原始问题一样-这是如何衡量对新功能的兴趣的方式.

谢谢!

It should be possible to use the R packages future and promises to trigger asynchronous (long running) processing via Shiny apps without freezing the rest of the app while the async process is running in another R process.

See:

https://cran.r-project.org/web/packages/promises/vignettes/intro.html
https://cran.r-project.org/web/packages/promises/vignettes/overview.html
https://cran.r-project.org/web/packages/promises/vignettes/futures.html
https://cran.r-project.org/web/packages/promises/vignettes/shiny.html

I got this to work in R-script-based environment but can't get this to work when I implement a simple shiny app with 2 functions. The "not-async" function is always blocked while the async function is running, but that should not be the case.

I have posted the same question on the GitHub repo of the package promises: https://github.com/rstudio/promises/issues/23

I am posting it here as well hoping someone can help.

The question is:

  1. Can you take a look at the shiny app example posted below and let me know why the async processing is blocking the app? (It should not block).
  2. Ideally, can you provide a small example of an app with a non-blocking async and normal functionality (accessible while the async is running)?

Environment

Mac OS 10.12

$ R --version
R version 3.4.3 (2017-11-30) -- "Kite-Eating Tree"

remove.packages("future")
remove.packages("promises")
remove.packages("shiny")

install.packages("future")
install.packages("devtools")
devtools::install_github("rstudio/promises")
devtools::install_github("rstudio/shiny")

> packageVersion("future")
[1] ‘1.8.1’
> packageVersion("promises")
[1] ‘1.0.1’
> packageVersion("shiny")
[1] ‘1.0.5.9000’

One side question on the shiny package version, https://rstudio.github.io/promises/articles/intro.html says it should be >=1.1, but even installing with devtools, the version remains 1.0.5... . Is this an issue or is there a typo in the doc?

First, you can use promises with Shiny outputs. If you’re using an async-compatible version of Shiny (version >=1.1), all of the built-in renderXXX functions can deal with either regular values or promises.

Example of issue

I have implemented this simple shiny app inspired from the example at the URLs mentioned above. The shiny app has 2 "sections":

  1. A button to trigger the "long running" async processing. This is simulated by a function read_csv_async which sleeps for a few seconds, reads a csv file into a data frame. The df is then rendered below the button.
  2. A simple functionality which should work at any time (including when the async processing has been triggered): it includes a slider defining a number of random values to be generated. We then render a histogram of these values.

The issue is that the second functionality (histogram plot update) is blocked while the async processing is occurring.

global.R

library("shiny")
library("promises")
library("dplyr")
library("future")

# path containing all files, including ui.R and server.R
setwd("/path/to/my/shiny/app/dir")   

plan(multiprocess)

# A function to simulate a long running process
read_csv_async = function(sleep, path){
      log_path = "./mylog.log"
      pid = Sys.getpid()
      write(x = paste(format(Sys.time(), "%Y-%m-%d %H:%M:%OS"), "pid:", pid, "Async process started"), file = log_path, append = TRUE)
      Sys.sleep(sleep)
      df = read.csv(path)
      write(x = paste(format(Sys.time(), "%Y-%m-%d %H:%M:%OS"), "pid:", pid, "Async process work completed\n"), file = log_path, append = TRUE)
      df
}

ui.R

fluidPage(
  actionButton(inputId = "submit_and_retrieve", label = "Submit short async analysis"),
  br(),
  br(),
  tableOutput("user_content"),

  br(),
  br(),
  br(),
  hr(),

  sliderInput(inputId = "hist_slider_val",
              label = "Histogram slider",
              value = 25, 
              min = 1,
              max = 100),

  plotOutput("userHist")
)

server.R

function(input, output){
    # When button is clicked
    # load csv asynchronously and render table
    data_promise = eventReactive(input$submit_and_retrieve, {
        future({ read_csv_async(10, "./data.csv") }) 
    })
   output$user_content <- renderTable({
     data_promise() %...>% head(5)
    })


  # Render a new histogram 
  # every time the slider is moved
  output$userHist = renderPlot({
    hist(rnorm(input$hist_slider_val))
  })
}

data.csv

Column1,Column2
foo,2
bar,5
baz,0

Thanks!

解决方案

So this behavior is normal, see the response of the package developer at https://github.com/rstudio/promises/issues/23

Summary:

In shiny apps, one R process can be shared by multiple users. If one user submits a long running task, then all the other users sharing the same underlying R process are blocked. The goal of promises is to avoid this. So promises will prevent blocking between "user sessions" within one R process but not within a single "user session".

The author of the package mentioned that this feature is not supported yet and that it may be added if enough people ask for it. If you are looking for this, please go the GitHub issue and like the original question - this is how interest for new features is measured.

Thanks!

这篇关于异步进程阻止R Shiny应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆