将包附加到 R 中的 "temporary" 搜索路径
attaching packages to a "temporary" search path in R
在函数内部,我正在获取脚本:
f <- function(){
source("~/Desktop/sourceme.R") # source someone elses script
# do some stuff to the variables read in
}
f()
search() # library sourceme.R attaches is all the way in the back!
不幸的是,我正在采购的脚本并不完全在我的控制之下。他们调用 library(somePackage)
,这会污染搜索路径。
如果 sourceme.R
的作者希望 he/she 附加的包位于全局环境的顶部 level/close,这主要是个问题。如果我自己附上了一些屏蔽了一些函数名称的包 he/she 期望可用,那就不好了。
有没有一种方法可以获取脚本的源代码,但不知何故可以创建我自己的临时搜索路径,该路径在函数完成后“重置”运行?
一种方法是“快照”您当前的搜索路径并稍后尝试return:
search.snapshot <- local({
.snap <- character(0)
function(restore = FALSE) {
if (restore) {
if (is.null(.snap)) {
return(character(0))
} else {
extras <- setdiff(search(), .snap)
# may not work if DLLs are loaded
for (pkg in extras) {
suppressWarnings(detach(pkg, character.only = TRUE, unload = TRUE))
}
return(extras)
}
} else .snap <<- search()
}
})
进行中:
search.snapshot() # store current state
get(".snap", envir = environment(search.snapshot)) # view snapshot
# [1] ".GlobalEnv" "ESSR" "package:stats"
# [4] "package:graphics" "package:grDevices" "package:utils"
# [7] "package:datasets" "package:r2" "package:methods"
# [10] "Autoloads" "package:base"
library(ggplot2)
library(zoo)
# Attaching package: 'zoo'
# The following objects are masked from 'package:base':
# as.Date, as.Date.numeric
library(dplyr)
# Attaching package: 'dplyr'
# The following objects are masked from 'package:stats':
# filter, lag
# The following objects are masked from 'package:base':
# intersect, setdiff, setequal, union
search()
# [1] ".GlobalEnv" "package:dplyr" "package:zoo"
# [4] "package:ggplot2" "ESSR" "package:stats"
# [7] "package:graphics" "package:grDevices" "package:utils"
# [10] "package:datasets" "package:r2" "package:methods"
# [13] "Autoloads" "package:base"
search.snapshot(TRUE) # returns detached packages
# [1] "package:dplyr" "package:zoo" "package:ggplot2"
search()
# [1] ".GlobalEnv" "ESSR" "package:stats"
# [4] "package:graphics" "package:grDevices" "package:utils"
# [7] "package:datasets" "package:r2" "package:methods"
# [10] "Autoloads" "package:base"
我有点自信(未经验证)这并不总是适用于所有包,可能是由于 and/or 加载的 DLL 的依赖性。您可以尝试将 force=TRUE
添加到 detach
调用中,不确定这样做是否会更好或者可能有其他不受欢迎的 side-effects.
我会考虑使用 callr
包在单独的 R 进程中获取脚本,然后 return 由来源文件创建的环境。
通过使用单独的 R 进程,这将防止您的搜索路径被污染。我猜想在您确实想要的全局环境中可能会有一些副作用(例如定义变量的新函数)。 source
函数的 local
参数允许您指定解析脚本的执行位置。如果您 return 来自其他 R 进程的这个环境,您可以访问您需要的任何结果。
不确定你的是什么样子,但说我有这个文件可以修改搜索路径:
# messWithSearchPath.R
library(dplyr)
a <- data.frame(groupID = rep(1:3, 10), value = rnorm(30))
b <- a %>%
group_by(groupID) %>%
summarize(agg = sum(value))
从我的顶级脚本中,我将编写一个包装函数以在新环境中获取它并让 callr
执行此函数:
RogueScript <- function(){
rogueEnv <- new.env()
source("messWIthSearchPath.R", local = rogueEnv)
rogueEnv
}
before <- search()
scriptResults <- callr::r(RogueScript)
scriptResults$b
#> groupID agg
#> 1 1 -2.871642
#> 2 2 3.368499
#> 3 3 1.159509
identical(before, search())
#> [1] TRUE
如果脚本有其他副作用(例如设置选项或建立外部连接),此方法可能不起作用。可能有变通方法,具体取决于它们的用途,但如果您只想创建 variables/functions,这应该可行。它还可以防止脚本相互冲突,而不仅仅是您的顶级脚本。
在函数内部,我正在获取脚本:
f <- function(){
source("~/Desktop/sourceme.R") # source someone elses script
# do some stuff to the variables read in
}
f()
search() # library sourceme.R attaches is all the way in the back!
不幸的是,我正在采购的脚本并不完全在我的控制之下。他们调用 library(somePackage)
,这会污染搜索路径。
如果 sourceme.R
的作者希望 he/she 附加的包位于全局环境的顶部 level/close,这主要是个问题。如果我自己附上了一些屏蔽了一些函数名称的包 he/she 期望可用,那就不好了。
有没有一种方法可以获取脚本的源代码,但不知何故可以创建我自己的临时搜索路径,该路径在函数完成后“重置”运行?
一种方法是“快照”您当前的搜索路径并稍后尝试return:
search.snapshot <- local({
.snap <- character(0)
function(restore = FALSE) {
if (restore) {
if (is.null(.snap)) {
return(character(0))
} else {
extras <- setdiff(search(), .snap)
# may not work if DLLs are loaded
for (pkg in extras) {
suppressWarnings(detach(pkg, character.only = TRUE, unload = TRUE))
}
return(extras)
}
} else .snap <<- search()
}
})
进行中:
search.snapshot() # store current state
get(".snap", envir = environment(search.snapshot)) # view snapshot
# [1] ".GlobalEnv" "ESSR" "package:stats"
# [4] "package:graphics" "package:grDevices" "package:utils"
# [7] "package:datasets" "package:r2" "package:methods"
# [10] "Autoloads" "package:base"
library(ggplot2)
library(zoo)
# Attaching package: 'zoo'
# The following objects are masked from 'package:base':
# as.Date, as.Date.numeric
library(dplyr)
# Attaching package: 'dplyr'
# The following objects are masked from 'package:stats':
# filter, lag
# The following objects are masked from 'package:base':
# intersect, setdiff, setequal, union
search()
# [1] ".GlobalEnv" "package:dplyr" "package:zoo"
# [4] "package:ggplot2" "ESSR" "package:stats"
# [7] "package:graphics" "package:grDevices" "package:utils"
# [10] "package:datasets" "package:r2" "package:methods"
# [13] "Autoloads" "package:base"
search.snapshot(TRUE) # returns detached packages
# [1] "package:dplyr" "package:zoo" "package:ggplot2"
search()
# [1] ".GlobalEnv" "ESSR" "package:stats"
# [4] "package:graphics" "package:grDevices" "package:utils"
# [7] "package:datasets" "package:r2" "package:methods"
# [10] "Autoloads" "package:base"
我有点自信(未经验证)这并不总是适用于所有包,可能是由于 and/or 加载的 DLL 的依赖性。您可以尝试将 force=TRUE
添加到 detach
调用中,不确定这样做是否会更好或者可能有其他不受欢迎的 side-effects.
我会考虑使用 callr
包在单独的 R 进程中获取脚本,然后 return 由来源文件创建的环境。
通过使用单独的 R 进程,这将防止您的搜索路径被污染。我猜想在您确实想要的全局环境中可能会有一些副作用(例如定义变量的新函数)。 source
函数的 local
参数允许您指定解析脚本的执行位置。如果您 return 来自其他 R 进程的这个环境,您可以访问您需要的任何结果。
不确定你的是什么样子,但说我有这个文件可以修改搜索路径:
# messWithSearchPath.R
library(dplyr)
a <- data.frame(groupID = rep(1:3, 10), value = rnorm(30))
b <- a %>%
group_by(groupID) %>%
summarize(agg = sum(value))
从我的顶级脚本中,我将编写一个包装函数以在新环境中获取它并让 callr
执行此函数:
RogueScript <- function(){
rogueEnv <- new.env()
source("messWIthSearchPath.R", local = rogueEnv)
rogueEnv
}
before <- search()
scriptResults <- callr::r(RogueScript)
scriptResults$b
#> groupID agg
#> 1 1 -2.871642
#> 2 2 3.368499
#> 3 3 1.159509
identical(before, search())
#> [1] TRUE
如果脚本有其他副作用(例如设置选项或建立外部连接),此方法可能不起作用。可能有变通方法,具体取决于它们的用途,但如果您只想创建 variables/functions,这应该可行。它还可以防止脚本相互冲突,而不仅仅是您的顶级脚本。