卸载/分离R中所有已加载的命名空间和已附加的包

5

我遇到了附加包(sessionInfo()$otherPkgs)和命名空间(loadedNamespaces()) 污染全局范围的问题。因此我想在脚本开始时清除它们。

这个主题解决了部分问题,但关键差异是我想要卸载命名空间,而不仅仅是分离包。 Pacman 也很有趣,但似乎也无法解决问题。

library(dbplyr)
names(sessionInfo()$otherPkgs)
lapply(paste("package:", names(sessionInfo()$otherPkgs), sep=""), 
   detach, character.only = TRUE, unload = TRUE)
# `dbplyr` is detached
names(sessionInfo()$otherPkgs)

然而,对于卸载已加载的命名空间,类似的方法要困难得多,因为依赖其他命名空间的软件包必须首先卸载。

这是我的尝试:

# Recursive unload which checks for reverse dependencies (children) along the way
# and unloads them first
myunload <- function(pkg) {
    # Get child (reverse-dependent) packages that have loaded namespaces
    child_pkgs <- unlist(tools::dependsOnPkgs(pkg, which = c("Depends", "Imports"), reverse = T))
    child_pkgs <- child_pkgs[which(child_pkgs %in% loadedNamespaces())]
    # Recursively unload child packages
    lapply(child_pkgs, myunload)
    unloadNamespace(pkg)
}
# Apply over all our loaded namespaces
lapply(loadedNamespaces(), myunload)

测试它:

lapply(loadedNamespaces(), myunload)

卸载程序包时出错:Error in unloadNamespace(pkg) : 由于“grid”、“graphics”、“stats”导入了“grDevices”命名空间,因此无法卸载

看起来它正在尝试卸载基础程序包,这不是我的意图。我不确定如何指定不使用基础程序包。

我想使用 detach(..., unload=T, character.only=T, force=T) 但这会失败,正如文档中所述:

如果该命名空间被另一个命名空间导入或者 unload 为 FALSE,则不会发生卸载。

是否有更简单或有效的方法可以卸载所有命名空间,包括那些可能被其他命名空间导入的命名空间?如果该命名空间被另一个命名空间导入或者 unload 为 FALSE,则不会发生卸载。


这是一个非常好的问题,我也遇到了同样的问题,有没有人有任何想法如何解决它? - Lodyk Vovchak
一种方法是在 RStudio 内部重新启动 r,使用 .rs.restartR()。但对我来说,它仅起作用了一次,之后,每次尝试重新启动 RStudio 时,它都会卡住。 - Lodyk Vovchak
1个回答

0
我们可以使用一个while循环来实现这个功能,它会一直尝试直到除了基本包bpk"rstudioapi"和自定义的exclusions之外的所有不需要的内容都被卸载。
更具体地说,它会跳过由于每次迭代中的依赖关系而无法卸载的命名空间,确保它们最后被卸载。
unload_pkgs <- \(exc=NULL) {
  bpk <- c("compiler", "graphics", "tools", "utils", "grDevices", "stats", 
           "datasets", "methods", "base", "rstudioapi") |> c(exc)
  while (length(setdiff(loadedNamespaces(), bpk)) > 0) {
    lapply(setdiff(loadedNamespaces(), bpk), \(x) {
      try(unloadNamespace(x), silent=TRUE)
    })
  }
}

使用方法

## load some packages
library(ggplot2)
library(Rcpp)
library(MASS)

loadedNamespaces()
# [1] "Rcpp"       "assertthat" "utf8"       "R6"        
# [5] "ggplot2"    "pillar"     "utils"      "rlang"     
# [9] "rstudioapi" "munsell"    "compiler"   "pkgconfig" 
# [13] "stats"      "tidyselect" "tibble"     "grDevices" 
# [17] "fansi"      "withr"      "dplyr"      "MASS"      
# [21] "grid"       "gtable"     "lifecycle"  "DBI"       
# [25] "magrittr"   "datasets"   "scales"     "cli"       
# [29] "graphics"   "vctrs"      "generics"   "base"      
# [33] "tools"      "glue"       "colorspace" "methods"   

unload_pkgs(exc=c('Rcpp', 'MASS'))  ## exclude 'Rcpp' and 'MASS' from unload
loadedNamespaces()
# [1] "Rcpp"       "grDevices"  "MASS"       "datasets"  
# [5] "utils"      "rstudioapi" "graphics"   "base"      
# [9] "tools"      "compiler"   "stats"      "methods" 

unload_pkgs()  ## unload ALL non-base
loadedNamespaces()
# [1] "grDevices"  "datasets"   "utils"      "rstudioapi"
# [5] "graphics"   "base"       "tools"      "compiler"  
# [9] "stats"      "methods" 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接