shinyapps.io部署Shiny应用后如何自动安装所需R包
shinyapps.io 部署后动态安装用户代码依赖R包实现方案
核心报错原因
shinyapps.io 部署的应用运行时,默认的R系统库路径为只读权限,直接调用install.packages()默认向系统库写入文件时,就会触发'lib = ".../lib/R/library"' is not writable的报错。由于无法提前预知用户输入代码用到的所有包,可通过配置运行时可写包路径+执行前自动扫描安装依赖的方式实现部署后动态装包。
具体实现步骤
第一步:应用启动时初始化可写包存储路径
在app.R文件最开头添加以下代码,将运行时临时目录下的自定义路径加入R包搜索路径,临时目录在shinyapps.io实例运行期间具备完整写入权限:# 初始化可写用户包目录 user_lib <- file.path(tempdir(), "custom_r_pkgs") dir.create(user_lib, recursive = TRUE, showWarnings = FALSE) # 将自定义目录加到包搜索路径最优先位置 .libPaths(c(user_lib, .libPaths()))第二步:封装依赖自动扫描安装函数
写一个前置处理函数,在用户代码执行前自动解析代码中调用的所有第三方包,对未安装的包自动安装到自定义可写路径,无需用户手动写install.packages():auto_prepare_deps <- function(user_code) { # 正则匹配代码中所有第三方包调用:library()/require()/pkg::func()形式 match_res <- regmatches( user_code, gregexpr( "(?:library|require)\\(['\"]?([a-zA-Z0-9\\.]+)['\"]?\\)|([a-zA-Z0-9\\.]+)::", user_code, perl = TRUE ) )[[1]] # 提取清洗包名,过滤R自带基础包 all_pkgs <- gsub("(?:library|require)\\(['\"]?|['\"]?\\)|::", "", match_res) base_pkgs <- rownames(installed.packages(priority = "base")) need_pkgs <- unique(setdiff(all_pkgs, c(base_pkgs, ""))) # 安装缺失包 missing_pkgs <- need_pkgs[!vapply(need_pkgs, requireNamespace, logical(1), lib.loc = user_lib, quietly = TRUE)] if (length(missing_pkgs) > 0) { install.packages( missing_pkgs, lib = user_lib, repos = "https://cloud.r-project.org/", quiet = TRUE, ask = FALSE ) } # 自动加载所有依赖包(可选,适配用户未手动写library的场景) lapply(need_pkgs, function(p) { suppressPackageStartupMessages(library(p, character.only = TRUE, lib.loc = user_lib)) }) }第三步:嵌入用户代码执行逻辑
在你原有执行用户输入代码的逻辑前,先调用依赖准备函数,再执行用户代码即可。示例:# 假设input$user_code是前端文本框接收的用户输入代码字符串 observeEvent(input$run_code, { user_code <- input$user_code # 提前处理依赖 auto_prepare_deps(user_code) # 执行用户代码,捕获输出/结果返回前端 res <- tryCatch( eval(parse(text = user_code)), error = function(e) paste("运行错误:", e$message) ) # 把res输出到前端即可 })
注意事项
- shinyapps.io的临时目录会在实例休眠、重启后清空,首次调用未预装的包时会有几秒到几十秒的安装等待时间,属于正常现象
- 可以在依赖处理逻辑中提前正则替换掉用户自行写的
install.packages()调用,避免再次触发只读路径报错 - 如果需要支持Bioconductor生态的包,只需在应用部署阶段预先安装
BiocManager,在自动安装逻辑中增加Bioconductor包的判断分支,调用BiocManager::install()安装到user_lib路径即可 - 受shinyapps.io实例运行内存、超时规则限制,体积过大的包安装可能触发超时,可按需增加包大小校验、安装超时提示
- 该方案默认从CRAN官方源安装包,若需要使用自定义源,修改
install.packages的repos参数即可
内容的提问来源于stack exchange,提问作者Joachim Schork
相关产品推荐
相关产品推荐

