仅在本地范围内加载库R

是否可能library()仅影响本地范围?

例如,我的脚本有一个lapply循环,该循环使用其他脚本中的source()代码;这些脚本加载了它们自己的库,但是我希望在执行这些脚本中的代码之后清理名称空间,以便脚本1调用的程序包A中的函数不会掩盖脚本2调用的程序包B中的函数。

我知道有modulesimport软件包之类的完整解决方案,但我希望首先有一个更简单的base R解决方案,仅在需要时才进行扩展。

iCMS 回答:仅在本地范围内加载库R

使用loadNamespace("pkg")将加载'pkg'软件包的名称空间。使用library("pkg")还将把'pkg'包附加到R的搜索路径。您可以查看使用loadedNamespaces()加载了哪些名称空间,以及使用search()附加了哪些软件包。这些属性对于R是全局的。换句话说,实际上不可能将它们设置为局部。

如果您希望在函数/ map-reduce调用中使用library(),而不会导致library()在当前R会话中附加该程序包,则可以按照其他人的建议评估调用在外部R程序中。

(免责声明:我是作者)我建议为此使用期货(future),您可以通过future.callr外部评估期货-callr的未来包装。 未来的框架将负责导出外部R流程所需的对象。 这是一个示例:

library(future)
plan(future.callr::callr,workers = 1)
y <- lapply((1:3)/4,FUN = function(x) value(future({
  library(gtools)
  logit(x)
})))

请注意如何创建期货并立即获取其价值,即value(future(...))。为了阐明这一事实,您可以使用:

eval_via_future <- function(expr,substitute = TRUE,envir = parent.frame()) {
  if (substitute) expr <- substitute(expr)
  f <- future::future(expr,substitute = FALSE,envir = envir)
  future::value(f)
}
library(future)
plan(future.callr::callr,FUN = function(x) eval_via_future({
  library(gtools)
  logit(x)
})))

如果您要避免让用户指定plan(),请执行以下操作:

eval_via_callr <- function(expr,envir = parent.frame()) {
  oplan <- future::plan()
  on.exit(future::plan(oplan))
  future::plan(future.callr::callr,workers = 1)
  if (substitute) expr <- substitute(expr)
  f <- future::future(expr,envir = envir)
  future::value(f)
}

因此您可以这样做:

y <- lapply((1:3)/4,FUN = function(x) eval_via_callr({
  library(gtools)
  logit(x)
}))

不加载或附加 gtools (显然会加载未来调用者所需的其他软件包);

> loadedNamespaces()
 [1] "codetools"    "grDevices"    "listenv"      "future"       "ps"          
 [6] "memuse"       "clisymbols"   "prompt"       "digest"       "crayon"      
[11] "rappdirs"     "R6"           "future.callr" "datasets"     "utils"       
[16] "callr"        "graphics"     "base"         "tools"        "parallel"    
[21] "compiler"     "processx"     "stats"        "globals"      "methods"     

> search()
 [1] ".GlobalEnv"        "package:stats"     "package:graphics" 
 [4] "package:grDevices" "package:utils"     "package:datasets" 
 [7] "CBC tools"         "toolbox:default"   "package:methods"  
[10] "Autoloads"         "package:base" 

更新2020-07-26

这里是如何通过将来在外部R进程中获取R脚本的方法,同时又从主要R会话中提取了全局变量:

future_source <- function(file,envir = parent.frame(),...) {
  expr <- parse(file = file,keep.source = FALSE)
  expr <- bquote({..(expr)},splice = TRUE)
  future::future(expr,envir = envir,...)
}

source_via_callr <- function(file,workers = 1)
  f <- future_source(file,envir = envir)
  future::value(f)
}
## Two R scripts
cat("log(a)\n",file="a.R")
cat("library(gtools)\nlogit(a)\n",file="b.R")

## A global
a <- 0.42

## Source scripts in external process
y <- lapply(c("a.R","b.R"),FUN = source_via_callr)
本文链接:https://www.f2er.com/1866572.html

大家都在问