我想卸载软件包及其所有依存关系。但是我不想卸载以前用library()
装载的软件包或与用library()
装载的软件包相关的软件包。我该怎么办?
答案 0 :(得分:0)
编辑:我已经更新了对以上链接问题的回答,
显示了跟踪library
的显式用法的可能选择。
可以在下面的代码中使用它来计算attached
,而不用使用search
。
这是我使用remotes
软件包发现的一种可能性:
transitive_deps <- function(package, acc = character()) {
direct_deps <- remotes::local_package_deps(system.file(package = package))
filtered_deps <- setdiff(direct_deps, acc)
if (length(filtered_deps) == 0L) {
package
}
else {
acc <- union(acc, filtered_deps)
for (dep in filtered_deps) { acc <- union(acc, transitive_deps(dep, acc)) }
union(package, acc)
}
}
unload_deep <- function(package) {
# find all transitive dependencies of the package
deps <- transitive_deps(package) # alternatively: remotes::package_deps(package)$package
# do not unload base packages
deps <- setdiff(deps, installed.packages(priority = "base")[, "Package"])
# do not unload packages explicitly attached with library()
attached <- search()
deps <- setdiff(deps, substring(attached, unlist(gregexpr(":", attached)) + 1L)) # remove "package:" prefix
# first unload provided package
tryCatch(unloadNamespace(package), error = function(...) {
package <- paste0("package:", package)
if (package %in% search()) {
# at least try to detach it if some other package imports it
detach(package, character.only = TRUE)
}
})
deps <- setdiff(deps, package)
# try to unload remaining
while (length(deps) > 0L) {
unloaded_one <- FALSE
for (dep in deps) {
flag <- try(unloadNamespace(dep), silent = TRUE)
if (!inherits(flag, "try-error")) {
unloaded_one <- TRUE
break
}
}
if (unloaded_one) {
deps <- setdiff(deps, dep)
}
else {
# could not unload any, must be used by other unrelated packages
break
}
}
# return
invisible()
}
您需要在package
中传递一个字符。
另外,如代码注释中所述,
您可以使用remotes::package_deps(package)$package
而不是transitive_deps
助手。
我认为前者已经过滤了base
个软件包,
但我相信它会在您每次使用时进行在线检查。
transitive_deps
助手远非完美,
它只是试图找到直接的依赖
(这是remotes::local_package_deps
返回的内容)
递归地
希望通过使用acc
来积累已经看到的软件包来避免重复。
卸载软件包的顺序很重要,
因为您不能卸载由当前加载的另一个软件包导入的软件包。
不幸的是,deps
中的顺序并不总是那么完美,
这就是循环中存在try
的原因,
跳过有问题的程序包,直到所有相关程序包都已卸载。