用于在R中分离环境的源脚本,而不是全局环境

Meg*_*ron 12 r r-environment

是否有一种方法可以source()R中的脚本附加为全局环境(.GlobalEnv)的父级?

目前,当我获取脚本时,该脚本的所有变量和函数都出现在我的全局(交互)环境中.我想在搜索路径中包含这些变量和函数,但不包括在内.GlobalEnv.也就是说,我希望源脚本的行为类似于附加的包,它附加在全局环境和基础环境之间(参见高级R 环境中的图)

在此输入图像描述

Meg*_*ron 9

以下环境插入似乎可以实现所需的功能:

检查当前搜索路径:

search()
# [1] ".GlobalEnv"        "package:stats"     "package:graphics"
# [4] "package:grDevices" "package:utils"     "package:datasets"
# [7] "package:methods"   "Autoloads"         "package:base"
Run Code Online (Sandbox Code Playgroud)

为源包添加新环境并localsource()ing时使用参数:

myEnv <- new.env()    
source("some_other_script.R", local=myEnv)
attach(myEnv, name="sourced_scripts")
Run Code Online (Sandbox Code Playgroud)

检查搜索路径:

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"
Run Code Online (Sandbox Code Playgroud)

请注意,我们attach()是采购的新环境,因此dplyr在搜索路径中附加在我们的脚本环境之后。


Jth*_*rpe 7

像脚本一样打包脚本来获取脚本的最简单方法(即,在调用R脚本中定义的函数时,词法作用域不会导致使用全局环境中定义的变量)。的父项是.BaseNamespaceEnv,然后source()使用该环境进行调用。

例如,如果您具有如下脚本:

# << my-script.R >>
my_fun <- function(x){x + y}
Run Code Online (Sandbox Code Playgroud)

然后在控制台上评估以下内容,不会产生错误,就像my_fun在其自己的程序包中定义的一样:

source("my-script.R")
y = 2
my_fun(1)
#> 3
Run Code Online (Sandbox Code Playgroud)

但是,如果您创建的环境的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
Run Code Online (Sandbox Code Playgroud)

  • 感觉就像您正在重新发明轮子,因为已经存在一种用于运行批处理R脚本的机制(即`help(“ Rscript”)`),恕我直言,R是一种糟糕的语言,用于单独运行代码。我个人将使用另一种语言Python,NodeJS,Powershell或Bash或任何您喜欢的擅长管理子流程的语言来为R会话编写脚本。 (2认同)

Gre*_*now 5

source文档中,local参数可以是一个环境,它决定了源表达式在哪里计算。

这表明您可以创建一个新环境,运行时source将此环境传递给local,然后attach将环境传递给搜索路径。

或者您可以使用 attach withwhat=NULL创建一个空环境,保存返回值,并将其传递给localin source

tmp <- attach(what=NULL)
source('test.R', local=tmp)
Run Code Online (Sandbox Code Playgroud)

或作为一行:

source('test.R', local=attach(NULL))
Run Code Online (Sandbox Code Playgroud)

  • 这种方法的一个问题是插入了源脚本环境并且脚本中附加的任何库都是子库 - 所以它找不到库 (2认同)

Kon*_*rad 5

我也想使用sys.source功能的解决方案。使用envirtoplevel.env参数可以方便地绕过全局环境(IMHO)。根据链接的文档:

sys.source [p]解析给定文件中的表达式,然后在指定的环境中对其求值。

tstEnv <- new.env()
sys.source(file = "tst.R", envir = tstEnv, toplevel.env = tstEnv)
Run Code Online (Sandbox Code Playgroud)

其中tst.R包含:

a <- 1
b <- 1
Run Code Online (Sandbox Code Playgroud)

结果:

ls(envir = .GlobalEnv)
# [1] "tstEnv"
ls(envir = tstEnv)
# [1] "a" "b"
tstEnv$a
# [1] 1
Run Code Online (Sandbox Code Playgroud)