如何通过callr::r获取新R会话的.GlobalEnv
问题:如何获取callr新会话的全局环境?
我理解callr::r会在新的R会话中执行传入的函数。尝试返回.GlobalEnv以保留该新会话的全局环境时,发现匿名函数内的.GlobalEnv指向的是调用环境的全局环境。
背景是因RStudio存在bug,含非R代码块的Rmarkdown文档无法使用“run all chunks”功能,我想用callr::r在新会话中调用rmarkdown::render以避免命名冲突并保留中间结果,但返回的仍是原全局环境,请问如何获取新会话的.GlobalEnv?
代码示例:
i_am_defined_on_global_level <- "here" res <- callr::r(function() .GlobalEnv) names(res) # [1] "res" ".Random.seed" # [3] "i_am_defined_on_global_level"
render_report <- function(report = "myreport.Rmd", report_dir = here::here("report")) { report_env <- callr::r(function(report, report_dir) { rmarkdown::render(file.path(report_dir, report), output_dir = report_dir, envir = globalenv()) globalenv() }, list(report = report, report_dir = report_dir), show = TRUE, spinner = FALSE) report_env } results <- render_report()
解决方案
核心问题在于:环境对象无法跨R进程直接传递。当你在callr的新会话中返回globalenv()或.GlobalEnv时,callr在序列化返回对象的过程中,无法完整传递环境本身,反而可能因为序列化机制的问题,让你误以为拿到的是原会话的环境。
要获取新会话全局环境中的变量,正确的做法是在新会话内将全局环境转换为列表后再返回:
- 修改测试代码:
i_am_defined_on_global_level <- "here" res <- callr::r(function() as.list(globalenv())) names(res) # 此时只会返回新会话全局环境中的变量,比如 ".Random.seed"
- 针对你的
render_report函数,修改为:
render_report <- function(report = "myreport.Rmd", report_dir = here::here("report")) { report_env <- callr::r(function(report, report_dir) { # 在新会话的全局环境中渲染文档 rmarkdown::render(file.path(report_dir, report), output_dir = report_dir, envir = globalenv()) # 将新会话的全局环境转换为列表返回 as.list(globalenv()) }, list(report = report, report_dir = report_dir), show = TRUE, spinner = FALSE) report_env } results <- render_report()
这样返回的results就是新会话中渲染Rmarkdown后全局环境的所有变量集合,不会和原会话的变量混淆。
如果需要更精细地获取特定变量,也可以直接在新会话中返回指定变量,比如return(list(data = my_data, plot = my_plot)),避免返回整个环境的冗余内容。
内容的提问来源于stack exchange,提问作者thothal
相关产品推荐
相关产品推荐

