为什么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
函数评估上面的表达式,就像它们从外部上下文调用时的评估一样?
答案 0 :(得分:1)
Per ?.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
的输出。