R 包中的 reg.finalizer() 不会在 R 会话结束时执行

reg.finalizer() in an R package does not execute at the end of an R session

来自 R 中的文档 ?reg.finalizer

Inter alia, it provides a way to program code to be run at the end of an R session without manipulating .Last. For use in a package, it is often a good idea to set a finalizer on an object in the namespace: then it will be called at the end of the session, or soon after the namespace is unloaded if that is done during the session.

似乎我可以在 R 会话结束时使用 reg.finalizer() 到 运行 某些代码,但它对我不起作用。我在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)
> 
> 
$ 

如果您将终结器函数注册到包名 space 环境中,它就会起作用。您可以为此使用 .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)
}

未调用对象终结器函数,但由于您拥有全名space 环境,您可能不需要它。

我在 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 在终结器函数 executed/finished 之前关闭。我想同样的问题可能会出现在使用 message()

所以如果你想在退出时执行它,用消息测试函数可能会误导你。