繁体   English   中英

使R包易于使用用户的新文件进行更新

[英]Make R package easy to update with new files from users

首先,让我解释一下我来自Python世界,在那里我可以在shell中做我想做的事情:

$ export PYTHONPATH=~/myroot
$ mkdir -p ~/myroot/mypkg
$ touch ~/myroot/mypkg/__init__.py # this is the one bit of "magic" for Python
$ echo 'hello = "world"' > ~/myroot/mypkg/mymodule.py

然后在Python中:

>>> import mypkg.mymodule
>>> mypkg.mymodule.hello
'world'

我在那里所做的是创建一个易于被其他用户扩展的软件包。 我可以将〜/ myroot / mypkg签入到源代码管理中,其他用户以后可以仅使用文本编辑器向其中添加模块。 现在,我想在R中做等效的事情。这是到目前为止的内容:

$ export R_LIBS=~/myR # already this is bad: it makes install.packages() put things here!
$ mkdir -p ~/myR
$ echo 'hello = "world"' > /tmp/mycode.R

现在在R中:

> package.skeleton(name="mypkg", code_files="/tmp/mycode.R")

现在回到外壳:

$ R CMD build mypkg
$ R CMD INSTALL mypkg

现在回到R:

> library(mypkg)
> hello
"world"

这样行得通。 但是,现在我的同事如何在此程序包中添加新模块? 我希望他们能够进入并添加一个新的R文件,但是似乎我们接下来必须重做整个软件包构建过程,这很繁琐。 看来我们随后将最终签入许多生成的文件。 但最重要的是,代码在哪里去了? 一旦完成CMD INSTALL ,R就会知道我的代码是什么,但是它没有将文字文本(来自mycode.R )放在$R_LIBS下的任何位置(它是否“编译”了代码?我不确定)。

以前我们只是将source()我们的“模块”,但这并不是很好,因为它每次都会重新加载代码,因此间接(传递)依赖项最终会重新加载已经加载的内容。

我的问题是,人们如何在R中管理简单的,内部的,协作编辑的,源代码控制的,非二进制的,非编译的,共享的代码?

我在Linux上使用R 3.1.1。 如果该解决方案也可以在Windows上运行,那就太好了。

看来R像Python的import语句一样没有什么,所以我做了我自己的。 只需将其放入import.r类的文件中,然后通过$R_PROFILE

# this is sort of like Python's import statement, and lets us avoid redundant sourcing

.imports <- c("import") # module names imported so far, to avoid redundant imports (never import ourselves)

.importScriptPath <- function() {
  # returns the path of the executing script
  # see http://stackoverflow.com/questions/1815606

  # this will only work if the caller was loaded with source()
  filePath <- sys.frame(2)$ofile

  # if the caller was not loaded with source(), use the main script path
  if (length(filePath) == 0) {
    argv <- commandArgs(trailingOnly = FALSE)
    filePath <- substring(argv[grep("--file=", argv)], 8)
  }

  return (dirname(filePath))
}

import <- function(module) {
  # locates the given module (character or token), calls source() on it, and does nothing on subsequent calls

  module <- as.character(substitute(module)) # support import(foo) not only import("foo")

  if (module %in% .imports) {
    return(invisible())
  }

  moduleFilename <- paste0(gsub("\\.", "/", module), ".r") # allow import(foo.bar) as import("foo/bar")
  importPaths <- c(.importScriptPath()) # add more search paths here as desired

  for (importPath in importPaths) {
    modulePath <- file.path(importPath, moduleFilename)
    if (file.exists(modulePath)) {
      source(modulePath)
      .imports <<- append(.imports, module) # <<- updates the global variable so we skip it next time
      return(invisible())
    }
  }

  # last chance: try to load module as a standard library
  suppressPackageStartupMessages(library(module, character.only = TRUE))
  .imports <<- append(.imports, module)
  return(invisible())
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM