Installing packages from RProfile.site file

北慕城南 提交于 2019-12-05 21:28:35
GSee

I don't understand why you'd want to do this. Just have them point their .libPaths to the same place. i.e. instead of install.packages(...), just add a line in Rprofile.site that says

.libPaths('/path/to/common/libraries')
require("commonPackage")

Another thing that you might be able to do is make a system call. I don't know much about installing packages under Windows, but on Unix-alike, instead of using install.packages you could do something like this:

system("R --vanilla CMD INSTALL customPackage")

Among other things, the --vanilla flag causes R to be started without using the Rprofile.site file (Your problem is that the Rprofile.site file is being read when R starts, but the Rprofile.site file tells R to install a package which requires starting R, which in turns reads your Rprofile.site file... etc.). Presumably, R --no-site-file INSTALL customPackage would also work.

Edit

After consulting this SO answer, it looks like you could do something like this on Windows (assuming you have installed Rtools), although I haven't tested it.

system("Rcmd --vanilla INSTALL customPackage")

As GSee said, the problem is that install.packages runs R CMD INSTALL, which starts a new R process that reads the Rprofile.site file, resulting in a loop. Two ways to break the evil loop:

  1. Check that R is running interactively:

    if (interactive() && 
        length(grep("customPackage", installed.packages()[,1]))==0) { 
      install.packages("customPackage", repos=NULL, type="source") 
    }
    

    interactive() is FALSE when R CMD is running, so this breaks the loop.

  2. Set the R_PROFILE environment variable to an empty or invalid value, so the R session in R CMD won't run yours. Initialization at Start of an R Session says:

    If you want ‘~/.Renviron’ or ‘~/.Rprofile’ to be ignored by child R processes (such as those run by R CMD check and R CMD build), set the appropriate environment variable R_ENVIRON_USER or R_PROFILE_USER to (if possible, which it is not on Windows) "" or to the name of a non-existent file.

    Adapting that for Rprofile.site, you can set R_PROFILE to an empty or nonexistent file, before you call install.packages. For example:

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

    Then when R restarts to install packages, it reads an empty Rprofile.site file, so again you break the loop .

    If the call to install.packages is in .Rprofile, you can set R_PROFILE_USER in the same way.

The first method is simpler, and doesn't require you to worry about maybe overwriting an existing value of R_PROFILE.

You can use the function below to install package(s) without reloading .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())
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!