【发布时间】:2019-09-21 23:23:22
【问题描述】:
我想卸载包及其所有依赖项。但我不想卸载之前使用library() 加载的包或我使用library() 加载的包的依赖项的包。我该怎么做?
【问题讨论】:
-
@M.Viking 我已经看过它但没有找到“但我不想卸载我以前用
library()加载的包或我加载的包的依赖项的包与library()。”
我想卸载包及其所有依赖项。但我不想卸载之前使用library() 加载的包或我使用library() 加载的包的依赖项的包。我该怎么做?
【问题讨论】:
library() 加载的包或我加载的包的依赖项的包与library()。”
编辑:我已经更新了对上面链接的问题的回答,
显示跟踪 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 中传递一个字符。
此外,正如代码 cmets 中所述,
您可以使用 remotes::package_deps(package)$package 代替 transitive_deps 助手。
我认为前者已经过滤了base 包,
但我相信每次使用时它都会在线检查。
transitive_deps 助手远非完美,
它只是试图找到直接的依赖关系
(这是remotes::local_package_deps 返回的内容)
递归地,
希望通过使用acc 来累积已经看到的包来避免一些重复。
卸载包的顺序很重要,
因为您无法卸载由另一个当前加载的包导入的包。
不幸的是,deps 中的顺序并不总是完美的,
这就是为什么循环中有一个try,
跳过有问题的包,直到所有依赖包都被卸载。
【讨论】: