[英]Source script to separate environment in R, not the global environment
Is there a way to source()
a script in R such that it is attached as a parent to the global environment ( .GlobalEnv
)? 是否有一种方法可以在R中对脚本进行
source()
,使其作为父级附加到全局环境( .GlobalEnv
)?
Currently, when I source a script, all variables and functions of that script appear in my global (interactive) environment. 当前,当我提供脚本时,该脚本的所有变量和函数都出现在我的全局(交互)环境中。 I'd like to include these variables and functions in the search path, but not in
.GlobalEnv
. 我想在搜索路径中包括这些变量和函数,但不在
.GlobalEnv
。 That is, I'd like the sourced script to behave like an attached package, which gets attached between the global and base environments (see figure from Advanced R Environments ) 也就是说,我希望源脚本的行为类似于附加包,该附加包在全局环境和基本环境之间附加(请参阅Advanced R Environments中的图 )
The simplest way to source a script as if it was a package (ie such that lexical scoping won't result in the use of variables defined in the global environment when calling functions defined in your R script) is to create an environment that that is whose parent is the .BaseNamespaceEnv
, and then call source()
using that environment. 像脚本一样打包脚本来获取脚本的最简单方法(即,在调用R脚本中定义的函数时, 词法作用域不会导致使用全局环境中定义的变量)。其父是
.BaseNamespaceEnv
,然后使用该环境调用source()
。
For example if you have a script like this: 例如,如果您具有如下脚本:
# << my-script.R >>
my_fun <- function(x){x + y}
Then evaluating the following at the console, won't generate an error, as it would if my_fun
were defined within it's own package: 然后在控制台上评估以下内容,不会产生错误,就像在自己的包中定义了
my_fun
一样:
source("my-script.R")
y = 2
my_fun(1)
#> 3
However, if you create an environment whose search()
path does not include the Global Environment ( .GlobalEnv
) then you'll get a proper error when you call the function from your script: 但是,如果创建一个环境,其
search()
路径不包括全局环境( .GlobalEnv
),则从脚本中调用该函数时,将得到正确的错误:
# Create the environment:
ENV = new.env(parent = .BaseNamespaceEnv)
# Attache it to the search path so that objects in your environment can be
# found from the global environment (i.e. from the console):
attach(ENV)
# do things:
source("my-script.R",ENV)
y = 2
my_fun(1)
#> Error in .ENV$my_fun(3) : object 'y' not found
I would also like to a solution using sys.source
function. 我也想使用
sys.source
函数的解决方案。 Using envir
and toplevel.env
arguments allows for convenient (IMHO) bypassing of the global environment. 使用
envir
和toplevel.env
参数可以方便地绕过全局环境(IMHO)。 As per the linked documentation: 根据链接的文档:
sys.source
[p]arses expressions in the given file, and then successively evaluates them in the specified environment.sys.source
[p]sys.source
给定文件中的表达式,然后在指定的环境中连续对其求值。
tstEnv <- new.env()
sys.source(file = "tst.R", envir = tstEnv, toplevel.env = tstEnv)
where tst.R
contains: 其中
tst.R
包含:
a <- 1
b <- 1
ls(envir = .GlobalEnv)
# [1] "tstEnv"
ls(envir = tstEnv)
# [1] "a" "b"
tstEnv$a
# [1] 1
From the source
documentation, the local
argument can be an environment which determines where the sourced expressions are evaluated. 从
source
文档中, local
参数可以是一个确定在何处评估源表达式的环境。
This suggests that you could create a new environment, run source
passing this environment to local
, then attach
the environment to the search path. 这表明您可以创建一个新环境,运行将环境传递给
local
source
,然后attach
环境attach
到搜索路径。
Or you can use attach with what=NULL
to create an empty environment, save the return value, and pass that to local
in source
: 或者,您可以使用attach和
what=NULL
来创建一个空环境,保存返回值,并将其传递给source
local
:
tmp <- attach(what=NULL)
source('test.R', local=tmp)
or as a single line: 或作为一行:
source('test.R', local=attach(NULL))
The following environment insertion appears to achieve the desired functionality: 以下环境插入似乎可以实现所需的功能:
Check the current search path: 检查当前搜索路径:
search()
# [1] ".GlobalEnv" "package:stats" "package:graphics"
# [4] "package:grDevices" "package:utils" "package:datasets"
# [7] "package:methods" "Autoloads" "package:base"
Add new environment for sourced packages and use local
parameter when source()
ing: 为source包添加新环境,并在
source()
时使用local
参数:
myEnv <- new.env()
source("some_other_script.R", local=myEnv)
attach(myEnv, name="sourced_scripts")
Check the search path: 检查搜索路径:
search()
# [1] ".GlobalEnv" "sourced_scripts" "package:dplyr"
# [4] "package:stats" "package:graphics" "package:grDevices"
# [7] "package:utils" "package:datasets" "package:methods"
# [10] "Autoloads" "package:base"
Note that we attach()
the new environment after sourcing, so that dplyr
is attached after our script environment in the search path. 请注意,我们在获取资源后将
attach()
到新环境中,以便在搜索路径中的脚本环境之后附加dplyr
。
I'm not sure if my answer is any different from the answers given above, but I use the following code: 我不确定我的答案是否与上面给出的答案有所不同,但是我使用以下代码:
if (!exists('.env')) .env <- new.env() # creates an environment in which to store functions
if ('.env' %in% search()) detach(.env) # detaches .env if it already exists; does not "erase" functions previously stored in .env
func <- "filenameWhereSourceCodeIsStored"
source(paste0("C:/Users/JT/R/Functions/", func, ".R"), .env)
attach(.env)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.