Source script to separate environment in R, not the global environment

后端 未结 5 1844
闹比i
闹比i 2020-12-08 22:24

Is there a way to source() a script in R such that it is attached as a parent to the global environment (.GlobalEnv)?

Curr

相关标签:
5条回答
  • 2020-12-08 22:36

    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)
    
    0 讨论(0)
  • 2020-12-08 22:50

    I would also like to a solution using sys.source function. Using envir and toplevel.env arguments allows for convenient (IMHO) bypassing of the global environment. As per the linked documentation:

    sys.source [p]arses expressions in the given file, and then successively evaluates them in the specified environment.

    tstEnv <- new.env()
    sys.source(file = "tst.R", envir = tstEnv, toplevel.env = tstEnv)
    

    where tst.R contains:

    a <- 1
    b <- 1
    

    Results:

    ls(envir = .GlobalEnv)
    # [1] "tstEnv"
    ls(envir = tstEnv)
    # [1] "a" "b"
    tstEnv$a
    # [1] 1
    
    0 讨论(0)
  • 2020-12-08 22:51

    From the source documentation, the local argument can be an environment which determines where the sourced expressions are evaluated.

    This suggests that you could create a new environment, run source passing this environment to local, then attach the environment to the search path.

    Or you can use attach with what=NULL to create an empty environment, save the return value, and pass that to local in source:

    tmp <- attach(what=NULL)
    source('test.R', local=tmp)
    

    or as a single line:

    source('test.R', local=attach(NULL))
    
    0 讨论(0)
  • 2020-12-08 22:52

    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:

    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.

    0 讨论(0)
  • 2020-12-08 22:56

    The simplest way to source a script as if it was a package (i.e. 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.

    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:

    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:

    # 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
    
    0 讨论(0)
提交回复
热议问题