使用R包

时间:2017-06-15 11:15:17

标签: r deployment packages executable

在大多数脚本语言(例如Ruby,Python等)中,包管理器(例如gem,pip等)可以将脚本作为可执行文件安装,并将它们链接到PATH变量中引用的目录(例如/ usr / local /箱)。这将这些可执行脚本转换为shell命令,用户可以以独立方式在编程接口之外运行。

我想知道R中是否也存在这种可能性。鉴于R使用标准的Makefile,我想必须有办法这样做,尽管是非标准的。我已经知道我们可以在R脚本using the docopt package中读取命令行参数。但有没有办法在安装包时将脚本安装为可执行文件?

在这个主题上取得领导会很棒,但CRAN的一个工作示例也足够了。

2 个答案:

答案 0 :(得分:2)

简短(也很伤心)回答:你做不到。但请继续阅读。

推理:R只会将包内容写入自己的.libPaths()目录(或第一个,如果有几个),或者是用户指定的目录。

所以说,/usr/local/bin/根本无法触及。这是一种可辩护的策略。

这也很令人伤心 - 为了这个目的,我写了littler(也是CRAN page):可执行的R脚本。我们有数十个cron个工作中调用的工作人员。那么我们该怎么办?从包含脚本的程序包的scripts/子目录到/usr/local/bin一次性软链接。在软件包升级时,链接将作为软链接保留。

这就是我为例如做的所有examples shipping with littler以及来自其他软件包的更多信息。他们中的许多人也使用docopt

答案 1 :(得分:0)

我有一个相似的目标,这是我确定的解决方案。我向我的R包中添加了一个函数,该函数可以通过(详细地)创建从~/.local/bin到我的包exec文件夹中每个脚本的符号链接。

其他明智的默认位置可能是~/.local/lib/R/bin~/bin,但我最喜欢~/.local/bin

因此,在安装软件包后,我指导用户运行

Rscript -e 'mypackage::install_executable_scripts()'
#' @export
install_executable_scripts <- function(into = "~/.local/bin", overwrite = FALSE) {
  scripts <- dir(system.file("exec", package = "TKutils"),
                 full.names = TRUE)
  if (!dir.exists(into)) dir.create(into)
  into <- normalizePath(into)

  dests <- file.path(normalizePath(into), basename(scripts))
  if (any(already_exist <- file.exists(dests))) {
    if (overwrite) {
      to_del <- dests[already_exist]
      cli::cat_bullet("Deleting existing file: ", to_del,
                      bullet_col = "red")
      unlink(to_del)
    } else {
      cli::cat_bullet(sprintf(
        "Skipping script '%s' because a file by that name already exists at the destination",
        basename(scripts[already_exist])))
      scripts <- scripts[!already_exist]
      dests   <-   dests[!already_exist]
    }
  }
  if (length(scripts)) {
    file.symlink(scripts, dests)
    cli::cat_line("Created symlinks:")
    cli::cat_bullet(dests, " ->\n    ", scripts, bullet_col = "green")
  } else
    cli::cat_line("Nothing installed")

  PATHS <- normalizePath(strsplit(Sys.getenv("PATH"), ":", fixed = TRUE)[[1]],
                         mustWork = FALSE)
  if(!into %in% PATHS)
    warning(sprintf("destination '%s' is not on the PATH", into))
}