检测shiny是否运行R代码
Detecting whether shiny runs the R code
我想 运行 在两个位置编写 R 代码,一个是 Rnw 文件,另一个是交互式 shiny R markdown 文档。
因此,由于交互式闪亮组件在 Rnw 文件中不起作用,我需要的是 R 中的代码片段,用于检测是否加载交互式代码。
这 似乎 可行,但感觉像是一个快速破解:
if (exists("input")) { # input is provided by shiny
# interactive components like renderPlot for shiny
} else {
# non-interactive code for Rnw file
}
是否有稳定的解决方案或我可以访问的全局变量之类的东西来说明 shiny 目前是否 运行ning?或者我应该检查是否加载了 shiny
包?
什么最安全?
更新:在 Konrad Rudolphs 发表评论后,我重新考虑了我的方法。我的原始答案可以在下面找到。
我的方法与 Konrad Rudolphs 不同,可能与 OP 最初的想法不同。代码不言自明:
if (identical(rmarkdown::metadata$runtime, "shiny")) {
"shinyApp"
} else {
"static part"
}
我不会 运行 来自应用程序内部的这段代码,而是将其用作应用程序的包装器。如果代码位于 YAML 前端的 .Rmd
和 runtime: shiny
中,它将启动应用程序,否则,它将显示静态部分。
我想这应该可以满足您的要求,并且尽可能稳定。
我最初的想法是无论您是否在交互式文档中都进行硬编码:
document_is_interactive <- TRUE
if (document_is_interactive) {
# interactive components like renderPlot for shiny
} else {
# non-interactive code for Rnw file
}
虽然可能,但这可能会导致问题,因此会比 rmarkdown::metadata$runtime
的其他方法更不稳定。
此信息直接通过 Shiny 的 isRunning
function.
提供
以下已过时的答案:
您可以执行以下操作:
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'
}
现在您可以简单地在代码中使用 shiny_running()
并返回一个逻辑值,该值指示文档是否 运行 作为 Shiny 应用程序。
根据 discussion on Shiny the mailing list 的说法,这可能是(接近)最好的方法 — 但请注意讨论中提到的注意事项。
改编自code in the “modules” package。
或者,以下工作。它可能更适合 Shiny/RMarkdown 用例,但需要 YAML 前端的存在:它通过从中读取 runtime
值来工作。
shiny_running = function ()
identical(rmarkdown::metadata$runtime, 'shiny')
现在有一个函数 shiny::isRunning()
。
我想 运行 在两个位置编写 R 代码,一个是 Rnw 文件,另一个是交互式 shiny R markdown 文档。
因此,由于交互式闪亮组件在 Rnw 文件中不起作用,我需要的是 R 中的代码片段,用于检测是否加载交互式代码。
这 似乎 可行,但感觉像是一个快速破解:
if (exists("input")) { # input is provided by shiny
# interactive components like renderPlot for shiny
} else {
# non-interactive code for Rnw file
}
是否有稳定的解决方案或我可以访问的全局变量之类的东西来说明 shiny 目前是否 运行ning?或者我应该检查是否加载了 shiny
包?
什么最安全?
更新:在 Konrad Rudolphs 发表评论后,我重新考虑了我的方法。我的原始答案可以在下面找到。
我的方法与 Konrad Rudolphs 不同,可能与 OP 最初的想法不同。代码不言自明:
if (identical(rmarkdown::metadata$runtime, "shiny")) {
"shinyApp"
} else {
"static part"
}
我不会 运行 来自应用程序内部的这段代码,而是将其用作应用程序的包装器。如果代码位于 YAML 前端的 .Rmd
和 runtime: shiny
中,它将启动应用程序,否则,它将显示静态部分。
我想这应该可以满足您的要求,并且尽可能稳定。
我最初的想法是无论您是否在交互式文档中都进行硬编码:
document_is_interactive <- TRUE
if (document_is_interactive) {
# interactive components like renderPlot for shiny
} else {
# non-interactive code for Rnw file
}
虽然可能,但这可能会导致问题,因此会比 rmarkdown::metadata$runtime
的其他方法更不稳定。
此信息直接通过 Shiny 的 isRunning
function.
以下已过时的答案:
您可以执行以下操作:
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'
}
现在您可以简单地在代码中使用 shiny_running()
并返回一个逻辑值,该值指示文档是否 运行 作为 Shiny 应用程序。
根据 discussion on Shiny the mailing list 的说法,这可能是(接近)最好的方法 — 但请注意讨论中提到的注意事项。
改编自code in the “modules” package。
或者,以下工作。它可能更适合 Shiny/RMarkdown 用例,但需要 YAML 前端的存在:它通过从中读取 runtime
值来工作。
shiny_running = function ()
identical(rmarkdown::metadata$runtime, 'shiny')
现在有一个函数 shiny::isRunning()
。