我之前问过这个问题,但仍然无法解决。我正在尝试在启动R时安装自定义软件包。我们现在编写的许多代码都可供用户编辑。为了保护代码,我正在打包生产级别的代码,并让用户在启动时将其安装在机器上。
然而,当我尝试在RProfile.site文件中安装软件包时,程序会进入一个循环,R会不断地启动。我注意到,在R.中的库文件夹中,为包创建了一个锁定文件
这是我添加到站点文件的代码:
if(length(grep("customPackage", installed.packages()[,1]))==0) {
install.packages("customPackage", repos=NULL, type="source")
}
当我尝试在启动R(不更改站点文件)后运行此代码时,它会很好地安装软件包并继续运行。然而,当我尝试通过RProfile文件执行此操作时,它就会产生问题。
上次我尝试解决此问题时(https://stackoverflow.com/questions/10610067/installing-packages-upon-starting-r-session),我认为Justin建议对包使用if语句检查可以解决问题。但这似乎只解决了我从CRAN安装的软件包的问题,而不是自定义软件包。
如果能在这件事上提供任何帮助,我们将不胜感激!
我不明白你为什么要这么做。让他们把.libPaths
指向同一个地方。即不使用install.packages(...)
,只需在Rprofile.site中添加一行即可
.libPaths('/path/to/common/libraries')
require("commonPackage")
您可以做的另一件事是拨打system
电话。我不太了解在Windows下安装软件包,但在Unix上,你可以做这样的事情,而不是使用install.packages
:
system("R --vanilla CMD INSTALL customPackage")
除其他外,--vanilla
标志会导致R在不使用Rprofile.site文件的情况下启动(您的问题是R启动时正在读取Rprofile.sete文件,但Rprofile-site文件告诉R安装一个需要启动R的程序包,该程序包会依次读取您的Rprofile/site文件…等等)。据推测,R --no-site-file INSTALL customPackage
也会起作用。
编辑
在查阅了这个SO答案后,看起来你可以在Windows上做这样的事情(假设你已经安装了Rtools),尽管我还没有测试过。
system("Rcmd --vanilla INSTALL customPackage")
正如GSee所说,问题是install.packages
运行R CMD INSTALL
,它启动了一个新的R进程,读取Rprofile.site文件,从而导致循环。打破恶性循环的两种方法:
-
检查R是否以交互方式运行:
if (interactive() && length(grep("customPackage", installed.packages()[,1]))==0) { install.packages("customPackage", repos=NULL, type="source") }
当
R CMD
运行时,interactive()
为FALSE,因此这会中断循环。 -
将
R_PROFILE
环境变量设置为空值或无效值,这样R CMD
中的R会话就不会运行您的会话。R会话开始时的初始化说明:如果希望子R进程(例如由R CMD检查和R CMD构建运行的进程)忽略"~/.Renviron"或"~/.Rprofile",请将相应的环境变量R_ENVIRON_USER或R_PROFILE_USER设置为(如果可能,它不在Windows上)"或不存在的文件名。
将其适用于Rprofile.site,您可以在调用
install.packages
之前将R_PROFILE
设置为一个空的或不存在的文件。例如:if (length(grep("customPackage", installed.packages()[,1]))==0) { Sys.setenv(R_PROFILE = "/dev/null") install.packages("customPackage", repos=NULL, type="source") Sys.unsetenv("R_PROFILE") }
然后,当R重新启动以安装软件包时,它会读取一个空的Rprofile.site文件,因此您再次打破循环。
如果对
install.packages
的调用在.Rprofile中,则可以用相同的方式设置R_PROFILE_USER
。
第一种方法更简单,不需要担心可能会覆盖R_PROFILE
的现有值。
您可以使用下面的函数安装程序包,而无需重新加载.Rprofile
:
surround <- function(x, with) {
paste0(with, x, with)
}
peq <- function(x, y) paste(x, y, sep = " = ")
install.packages.vanilla <- function(pkgs, ...){
arguments <- as.list(match.call())[-1]
if(!"repos" %in% names(arguments)){
arguments$repos <- getOption("repos")
}
names_args <- names(arguments)
installArgs <- purrr::map_chr(seq_along(arguments),
function(i){
value <- arguments[[i]]
peq(names_args[i], ifelse(length(value)<2, deparse(value), as.character(list(value))))
})
installArgs <- stringr::str_replace_all(installArgs, """, "'")
installCmd <- paste0("utils::install.packages(",
paste(installArgs, collapse = ", "),
")")
fullCmd <- paste(
surround(file.path(R.home("bin"), "R"), with = """),
"--vanilla",
"--slave",
"-e",
surround(installCmd, with = """)
)
system(fullCmd)
return(invisible())
}