Detecting whether shiny runs the R code

There is now a function shiny::isRunning().


This information is provided directly via Shiny’s isRunning function.


Outdated answer below:

You can do the following:

shiny_running = function () {
    # Look for `runApp` call somewhere in the call stack.
    frames = sys.frames()
    calls = lapply(sys.calls(), `[[`, 1)
    call_name = function (call)
        if (is.function(call)) '<closure>' else deparse(call)
    call_names = vapply(calls, call_name, character(1))

    target_call = grep('^runApp$', call_names)

    if (length(target_call) == 0)
        return(FALSE)
    
    # Found a function called `runApp`, verify that it’s Shiny’s.
    target_frame = frames[[target_call]]
    namespace_frame = parent.env(target_frame)
    isNamespace(namespace_frame) && environmentName(namespace_frame) == 'shiny'
}

Now you can simply use shiny_running() in code and get a logical value back that indicates whether the document is run as a Shiny app.

This is probably (close to) the best way, according to a discussion on Shiny the mailing list — but do note the caveats mentioned in the discussion.

Adapted from code in the “modules” package.

Alternatively, the following works. It may be better suited for the Shiny/RMarkdown use-case, but requires the existence of the YAML front matter: It works by reading the runtime value from that.

shiny_running = function ()
    identical(rmarkdown::metadata$runtime, 'shiny')

Update: After Konrad Rudolphs comment I rethought my approach. My original answer can be found down below.

My approach is different from Konrad Rudolphs and maybe different to the OPs initial thoughts. The code speaks for itself:

if (identical(rmarkdown::metadata$runtime, "shiny")) {
  "shinyApp" 
} else {
  "static part"
}

I would not run this code from inside an app but use it as a wrapper around the app. If the code resides within a .Rmd with runtime: shiny in the YAML front matter it will start the app, if not, it will show the static part.

I guess that should do what you wanted, and be as stable as it could get.


My original thought would have been to hard code whether or not you were in an interactive document:

document_is_interactive <- TRUE

if (document_is_interactive) {
    # interactive components like renderPlot for shiny
} else {
    # non-interactive code for Rnw file
}

Although possible, this could lead to problems and would therefore be less stable than other the approach with rmarkdown::metadata$runtime.

Tags:

R

Rstudio

Shiny

Rnw