每次加载程序包时从Internet下载新数据

时间:2018-09-02 13:42:57

标签: r r-package

我有一个程序包,该程序包从Internet抓取数据并根据函数调用显示其内容。但是最近我从CRAN收到一条消息,表明安装Binary构建时数据变得过时(因为在utils.R中提到了该函数,并且在构建时已下载了该函数)。

在过去的几天里,我尝试了以下方法,但没有成功:

  • 使用<<-的全局变量,但它会生成一个CRAN注释,我也经历了一些答案,建议不要使用该方法 注意:no visible binding for global variable
  • 创建一个新环境,然后在其中添加此下载的对象,但是由于我无法在其他函数中访问该对象,因此它始终无法解决。参考:Where to create package environment variables?

这是当前的软件包文件:https://github.com/amrrs/tiobeindexr/tree/master/R

尝试过的解决方案:

zzz.r文件:

.onLoad <- function (libname, pkgname)
{

  assign("newEnv", new.env(hash = TRUE, parent = parent.frame()))

  newEnv$.all_tablesx789  <- rvest::html_table(xml2::read_html('https://www.tiobe.com/tiobe-index/'))


}

核心代码中的功能之一。

hall_of_fame <- function() {

  #check_data()

  #.GlobalEnv$.all_tablesx789 <- check_data()

  newEnv$.all_tablesx789[[4]]

}

该程序包构建良好,但是找不到该对象。错误如下:

Error in hall_of_fame() : object 'newEnv' not found

我只有几天的时间将我的软件包保存在CRAN上,我希望我已经提供了足够的数据来保存正在下载的问题。

谢谢!

2 个答案:

答案 0 :(得分:3)

考虑将memoise添加为依赖项,以便您可以使用最少的依赖项链免费获得会话内缓存,然后使用程序包环境和(仅出于娱乐目的)主动绑定。

创建新的环境(您可以将其粘贴在aaa.R中)

.pkgenv <- new.env(parent=emptyenv())

现在,(例如,在zzz.R中)设置一个执行表抓取的功能:

.get_tiboe_tables <- function(url) {
  message("Delete this since it's just to show caching works") # delete this
  content <- xml2::read_html(url)
  rvest::html_table(content)
}

并“记住”它(同样在zzz.R中):

get_tiboe_tables <- memoise::memoise(.get_tiboe_tables)

现在,创建一个活动绑定,该绑定将使我们像访问变量一样访问表(即不使用())。它比必要的要有趣得多(再次在zzz.R中):

makeActiveBinding(
  sym = "all_tables",
  fun = function() get_tiboe_tables('https://www.tiobe.com/tiobe-index/'),
  env = .pkgenv
)

现在,获取如下所示的值(注意,在“启动”缓存时,我们会收到“正在加载”消息:

str(.pkgenv$all_tables, 1)
## Delete this since it's just to show caching works ** the loading msg
## List of 4
##  $ :'data.frame':    20 obs. of  6 variables:
##  $ :'data.frame':    30 obs. of  3 variables:
##  $ :'data.frame':    15 obs. of  8 variables:
##  $ :'data.frame':    15 obs. of  2 variables:

在后续调用中,由于正在检索缓存的值,因此没有加载消息:

str(.pkgenv$all_tables, 1)
## List of 4
##  $ :'data.frame':    20 obs. of  6 variables:
##  $ :'data.frame':    30 obs. of  3 variables:
##  $ :'data.frame':    15 obs. of  8 variables:
##  $ :'data.frame':    15 obs. of  2 variables:

在下一个R会话中,它将刷新表。这样,就可以在不滥用站点的情况下获得新数据。您也可以使用文件排序规则来代替分类名称黑客攻击。

请注意,您也可以导出活动绑定,然后用户可以像使用变量一样使用它,而不必像调用函数一样。

答案 1 :(得分:1)

实际上,我采用的方法与上述answer略有不同。这是与Thomas'comment相关的,原因是我不想添加memoise作为依赖项并尝试了替代方法。

aaa.R中创建新程序包:

.pkgenv <- new.env(parent=emptyenv())

使用.onAttach()中的zzz.R将数据加载到环境中的表中

.onAttach <- function(libname, pkgname) {

  packageStartupMessage("Downloading TIOBE Index Data using your Internet...")

  tryCatch({
    .pkgenv$.get_tiboe_tables <- rvest::html_table(xml2::read_html("https://www.tiobe.com/tiobe-index/"))
  },
  error = function(e){
    packageStartupMessage("Downloading TIOBE Index data failed!")
    packageStartupMessage("Error Message:")
    packageStartupMessage(e)
    return(NA)
  })

}

我先前的错误似乎是我试图在.onLoad()自身内部创建新的环境。