R Shiny:当 运行 作为应用程序时,为什么源文件中的函数不能访问全局变量?
R Shiny: Why can't functions from source files access global variables when running as an app?
我已经构建了一个即将完成的 Shiny 仪表板。
我有多个包含各种函数的源文件,其中一些引用了在主 R 代码中定义的全局变量,而不是直接将它们作为参数传递。
我一直在通过 运行ning 代码段构建它并 testing/debugging 它,然后手动 运行ning shinyapp 函数来启动它。当我这样做时,该应用程序按预期工作。源文件中的函数可以读取全局变量。
但是,当我清除工作区并保存代码并使用“运行 App”功能一次 运行 整个事情时,它失败了,因为源文件功能不再找到全局变量,即使在全局环境中创建这些变量的代码出现在调用这些函数的任何代码之前。
请注意,如果我已经 运行 手动创建全局变量的代码部分和 运行 应用程序而不清除工作区,则函数可以读取它们。
有谁知道这是为什么,我该如何解决?
在下面的可重现示例中,全局变量的值为“Hello_World”。函数 test_function() 只是 returns 全局变量的值,然后用作 UI.
中的标题
主要 R 代码
# Import packages.
library(shiny)
library(shinydashboard)
library(DT)
library(data.table)
library(tidyverse)
library(dtplyr)
# Global Variables
global_var <- "Hello_World"
# Directory
directory <- ''
# Source function stored in separate file.
source(paste0(directory,"Test Function.R"))
# UI
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
id = "tabs",
menuItem("Test", tabName="tab_data",icon=icon("table"))
)
),
dashboardBody(
tabItem("tab_data",
fluidPage(
fluidRow(column(width=12,
h4(test_function())
))
)
)
)
)
# Server
server <- function(input, output, session) {
}
shinyApp(ui, server)
“测试 FUNCTION.R”
test_function <- function(){
return(global_var)
}
您需要在主目录中将它们创建为两个文件。代码失败并抛出错误:
Error in test_function() : object 'global_var' not found
如果我将代码的最后一行更改为以下内容,它允许代码 运行 手动分段。如果我突出显示整个代码并 运行 它,它就可以工作。 “Hello_World”显示为标题。
if(1==1){shinyApp(ui, server)}
现在,如果我改回该语句,现在全局变量已经由之前的 运行 创建,并且 运行 它作为一个应用程序,它可以工作。
我需要让它做的是当工作区清晰时,源函数能够从第一个 运行 读取全局变量。
前面: 使用 source("...", local = TRUE)
.
source
默认情况下将文件加载到全局环境,而不是本地环境。当您在控制台上工作时,两者是相同的。但是,当您 运行 应用程序时,应用程序的环境是不同的,并且不在全局环境中定义的函数的搜索路径中。
示例:
主文件:
global_var <- "Hello"
source("quux.R")
quux.R
:
func <- function() {
return(global_var)
}
采购后,我看到了
# Error in func() (from quux.R#2) : object 'global_var' not found
即
environment(func)
# <environment: R_GlobalEnv>
当我将主文件更改为
global_var <- "Hello"
source("quux.R", local = TRUE)
然后采购它就可以工作,就像 func()
本身一样。
environment(func)
# <environment: 0x0000000054a995e0>
func()
# [1] "Hello"
Test Function.R
无法访问 global_var
因为您在主文件中采购 Test Function.R
而不是相反。 (请参阅@r2evans 在 source
中使用 local = TRUE
的回答将为您解决问题。)
现在解释为什么当您的工作区中有 global_var
时它会起作用。
考虑这个例子 -
#Remove everything from your global environment
rm(list = ls())
#define a function which returns d
fn <- function() return(d)
#Call the function
fn()
Error in fn() : object 'd' not found
#Now define d in global environment
d <- 12
fn()
#[1] 12 #This returns 12
所以 R 默认在函数环境中寻找 d
,当它找不到它时,它会进入上一级,在这种情况下是全局环境,这次它获得 [= 的值18=] 所以它 returns 那。你的情况也一样。
我已经构建了一个即将完成的 Shiny 仪表板。
我有多个包含各种函数的源文件,其中一些引用了在主 R 代码中定义的全局变量,而不是直接将它们作为参数传递。
我一直在通过 运行ning 代码段构建它并 testing/debugging 它,然后手动 运行ning shinyapp 函数来启动它。当我这样做时,该应用程序按预期工作。源文件中的函数可以读取全局变量。
但是,当我清除工作区并保存代码并使用“运行 App”功能一次 运行 整个事情时,它失败了,因为源文件功能不再找到全局变量,即使在全局环境中创建这些变量的代码出现在调用这些函数的任何代码之前。
请注意,如果我已经 运行 手动创建全局变量的代码部分和 运行 应用程序而不清除工作区,则函数可以读取它们。
有谁知道这是为什么,我该如何解决?
在下面的可重现示例中,全局变量的值为“Hello_World”。函数 test_function() 只是 returns 全局变量的值,然后用作 UI.
中的标题主要 R 代码
# Import packages.
library(shiny)
library(shinydashboard)
library(DT)
library(data.table)
library(tidyverse)
library(dtplyr)
# Global Variables
global_var <- "Hello_World"
# Directory
directory <- ''
# Source function stored in separate file.
source(paste0(directory,"Test Function.R"))
# UI
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
id = "tabs",
menuItem("Test", tabName="tab_data",icon=icon("table"))
)
),
dashboardBody(
tabItem("tab_data",
fluidPage(
fluidRow(column(width=12,
h4(test_function())
))
)
)
)
)
# Server
server <- function(input, output, session) {
}
shinyApp(ui, server)
“测试 FUNCTION.R”
test_function <- function(){
return(global_var)
}
您需要在主目录中将它们创建为两个文件。代码失败并抛出错误:
Error in test_function() : object 'global_var' not found
如果我将代码的最后一行更改为以下内容,它允许代码 运行 手动分段。如果我突出显示整个代码并 运行 它,它就可以工作。 “Hello_World”显示为标题。
if(1==1){shinyApp(ui, server)}
现在,如果我改回该语句,现在全局变量已经由之前的 运行 创建,并且 运行 它作为一个应用程序,它可以工作。
我需要让它做的是当工作区清晰时,源函数能够从第一个 运行 读取全局变量。
前面: 使用 source("...", local = TRUE)
.
source
默认情况下将文件加载到全局环境,而不是本地环境。当您在控制台上工作时,两者是相同的。但是,当您 运行 应用程序时,应用程序的环境是不同的,并且不在全局环境中定义的函数的搜索路径中。
示例:
主文件:
global_var <- "Hello" source("quux.R")
quux.R
:func <- function() { return(global_var) }
采购后,我看到了
# Error in func() (from quux.R#2) : object 'global_var' not found
即
environment(func)
# <environment: R_GlobalEnv>
当我将主文件更改为
global_var <- "Hello"
source("quux.R", local = TRUE)
然后采购它就可以工作,就像 func()
本身一样。
environment(func)
# <environment: 0x0000000054a995e0>
func()
# [1] "Hello"
Test Function.R
无法访问 global_var
因为您在主文件中采购 Test Function.R
而不是相反。 (请参阅@r2evans 在 source
中使用 local = TRUE
的回答将为您解决问题。)
现在解释为什么当您的工作区中有 global_var
时它会起作用。
考虑这个例子 -
#Remove everything from your global environment
rm(list = ls())
#define a function which returns d
fn <- function() return(d)
#Call the function
fn()
Error in fn() : object 'd' not found
#Now define d in global environment
d <- 12
fn()
#[1] 12 #This returns 12
所以 R 默认在函数环境中寻找 d
,当它找不到它时,它会进入上一级,在这种情况下是全局环境,这次它获得 [= 的值18=] 所以它 returns 那。你的情况也一样。