【问题标题】:getNamespaceExports() called from within .onLoad package function从 .onLoad 包函数中调用的 getNamespaceExports()
【发布时间】:2018-02-09 13:18:13
【问题描述】:

为什么getNamespaceExports() 在从.onLoad 上下文自动调用时与从外部代码调用时返回不同的结果?

假设我们有一个名为testpackage 的R 包。这个包包含一个名为 hello.R 的 R 文件,其内容如下:

#' @export
package_var <- "some value"

#' @export
call_when_onload <- function(pkgname) {
  print(getNamespaceExports(pkgname))
  print(do.call("getNamespaceExports",list(pkgname),envir = globalenv()))
}

.onLoad <- function(libname, pkgname){
  print(sprintf("Executing onload procedure for package %s...",pkgname))
  call_when_onload(pkgname)
}

该包有一个 NAMESPACE 文件,如下所示:

# Generated by roxygen2: do not edit by hand

export(call_when_onload)
export(package_var)

现在问题来了:在记录和构建包之后,library("testpackage") 返回:

> library(testpackage)
[1] "Executing onload procedure for package testpackage..."
character(0)
character(0)

但是当我调用testpackage::call_when_onload("testpackage") 时,我得到以下输出(正如预期的那样):

> testpackage::call_when_onload("testpackage")
[1] "package_var"      "call_when_onload"
[1] "package_var"      "call_when_onload"

为什么?如何让.onLoad 函数像从外部上下文调用时一样评估上面的表达式?

【问题讨论】:

  • 会不会是.onLoad在导出的对象写入全局环境之前被执行?

标签: r scope namespaces package environment


【解决方案1】:

每个?.onLoad(强调我的):

加载后,loadNamespace 会查找名为 .onLoad 的钩子函数并调用它(带有两个未命名的参数)在密封命名空间和处理导出之前。

所以.onLoad 在从包中导出任何内容之前运行。

如果要获取所有导出的对象,一种方法是从包中读取NAMESPACE文件并进行处理:

f <- base::system.file("NAMESPACE", package="pkgname")
objs <- readLines(f)
exps <- objs[grepl("export", objs)]
sub("^export[^\\(]*\\(([^\\)]+)\\)", "\\1", exps)

可能需要进行一些调整以完全匹配getNamespaceExports 的输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-07
    • 2014-03-17
    • 1970-01-01
    • 2018-06-06
    • 2023-03-18
    • 2020-05-26
    • 1970-01-01
    相关资源
    最近更新 更多