Unload/Detach all Loaded Namespaces and Attached Packages in R
Asked Answered
M

1

5

I've had problems with the global scope being polluted by attached packages (sessionInfo()$otherPkgs) and namespaces (loadedNamespaces()). So I want to clear them at the beginning of my scripts.

Half the problem was solved in this thread. The key difference with this question is that I want to unload namespaces, not just detach packages. pacman is interesting as well, but doesn't seem to work either.

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

But similar approaches for unloading the loaded namespaces seem much more challenging because the packages which depend on others must be unloaded first.

Here's my attempt:

# 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)

Testing it:

lapply(loadedNamespaces(), myunload)

Error in unloadNamespace(pkg) : namespace ‘grDevices’ is imported by ‘grid’, ‘graphics’, ‘stats’ so cannot be unloaded

It looks like it's trying to unload base packages, which is not my intent. I'm not sure how to specify no base packages.

I would like to use detach(..., unload=T, character.only=T, force=T) but this fails, as explained in the documentation:

...if the namespace is imported by another namespace or unload is FALSE, no unloading will occur.

Is there a simpler method, or one which works, for unloading all namespaces, including those that might be imported by others? if the namespace is imported by another namespace or unload is FALSE, no unloading will occur.

Marmolada answered 24/9, 2019 at 20:43 Comment(2)
it is a very good question, got the same issue here, does any one has any incite how to tackle this?Buddy
one way would be to restart r within RStudio .rs.restartR(). But for me it worked only one time, afterwards, every time I try to restart RStudio it simply hangsBuddy
F
1

We may do this with a while loop that tryes until everything unwanted apart from base packages bpk, the "rstudioapi", and custom exclusions is unloaded.

More specifically, it skips non-unloadable namespaces due to dependencies in each iteration, ensuring that they are unloaded last.

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)
    })
  }
}

Usage

## 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" 
Fitzhugh answered 23/11, 2022 at 15:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.