来自R的文档?reg.finalizer
:
除其他外,它提供了一种方法,可以在R会话结束时编写代码,而无需操作
.Last
。要在包中使用,通常最好在命名空间中的对象上设置终结器:然后在会话结束时调用终结器,或者在会话期间完成命名空间后不久调用它。
似乎我可以使用reg.finalizer()
在R会话结束时运行某些代码,但它对我不起作用。我在https://github.com/yihui/finalizer-test准备了一个最小的包,它基本上包含以下代码:
e = new.env()
reg.finalizer(e, function(e) {
message('Bye!')
}, onexit = TRUE)
如果我只是在交互式R会话中运行上面的代码并退出会话,我可以看到消息Bye!
,但如果我安装上面的包(你可以使用devtools::install_github('yihui/finalizer-test')
),在R会话中加载它,并退出R会话,我没有看到消息。我想知道为什么在这种情况下不执行终结器。
FWIW,当我安装包时,我可以看到消息Bye!
:
$ R CMD INSTALL .
* installing to library ‘/Users/yihui/R’
* installing *source* package ‘finalizer’ ...
** R
** preparing package for lazy loading
No man pages found in package ‘finalizer’
** help
*** installing help indices
Bye!
** building package indices
** testing if installed package can be loaded
* DONE (finalizer)
当我运行以下命令时,我也看不到该消息:
$ R -e "library(finalizer)"
> library(finalizer)
>
>
$
如果将终结器函数注册到包名称空间环境,则它可以工作。您可以使用.onLoad
钩子:
e = new.env()
reg.finalizer(e, function(e) {
message('Object Bye!')
}, onexit = TRUE)
finalize <- function(env) {
print(ls(env))
message("Bye from Name space Finalizer")
}
.onLoad <- function(libname, pkgname) {
parent <- parent.env(environment())
print(str(parent))
reg.finalizer(parent, finalize, onexit= TRUE)
}
不会调用对象终结器函数,但由于您拥有整个命名空间环境,因此您可能不需要它。
我在https://github.com/mpbastos/finalizer-test上创建了一个测试包的分支:
> devtools::install_git("https://github.com/mpbastos/finalizer-test")
Downloading git repo https://github.com/mpbastos/finalizer-test
Installing finalizer
"C:/PROGRA~1/R/R-34~1.0/bin/x64/R" --no-site-file --no-environ --no-save \
--no-restore --quiet CMD INSTALL \
"C:/Users/mbastos/AppData/Local/Temp/RtmpOGymjQ/file5cf829e63957" \
--library="\\sharedfs/MyDocs6/mbastos/Documents/R/win-library/3.4" \
--install-tests
* installing *source* package 'finalizer' ...
** R
** preparing package for lazy loading
** help
No man pages found in package 'finalizer'
*** installing help indices
** building package indices
Object Bye!
** testing if installed package can be loaded
*** arch - i386
<environment: namespace:finalizer>
NULL
[1] "e" "finalize"
Bye from Name space Finalizer
*** arch - x64
<environment: namespace:finalizer>
NULL
[1] "e" "finalize"
Bye from Name space Finalizer
* DONE (finalizer)
> library(finalizer)
<environment: namespace:finalizer>
NULL
> q()
Save workspace image? [y/n/c]: n
[1] "e" "finalize"
Bye from Name space Finalizer
不是真正的答案(接受的答案很好),但我也注意到在某些情况下,当终结器在退出时运行时,像print和cat这样的函数不会产生可见的输出,至少在使用RStudio时。
我无法看到一个模式,但我猜有一个竞争条件,并且在某些情况下stdout在执行/完成终结函数之前关闭。而且我想同样的问题可能会起到使用message()的作用
因此,如果要在退出时执行它,则使用消息测试函数可能会误导您。