我不知道这对你当前的情况有多大的适应性,但是这里有一种方法可以让四个任务并行运行,获取它们的返回值,然后触发第五个表达式/函数。
前提是使用callr::r_bg
来运行单个文件。实际上,这会运行一个function
,而不是一个文件,因此我将修改这些文件的外观期望一点点。
我将编写一个辅助脚本,旨在模仿你的四个脚本之一。我猜你也想能够正常地源化它(直接运行它而不是作为一个函数),所以我将生成脚本文件,使它“知道”它是被源化还是直接运行(基于Rscript detect if R script is being called/sourced from another script)。 (如果你了解python
,这类似于python的if __name__ == "__main__"
技巧。)
辅助脚本名为somescript.R
。
somefunc <- function(seconds) {
Sys.sleep(seconds)
return(mtcars[sample(nrow(mtcars),2),1:3])
}
if (sys.nframe() == 0L) {
somefunc(3)
}
作为演示,如果在控制台上执行
source
,这仅仅定义了函数(或多个函数,如果你需要的话),它并不会执行最后一个
if
块中的代码。
system.time(source("~/StackOverflow/14182669/somescript.R"))
但如果我在终端中使用 Rscript
运行这个程序,
$ time /c/R/R-4.0.2/bin/x64/Rscript somescript.R
mpg cyl disp
Merc 280C 17.8 6 167.6
Mazda RX4 Wag 21.0 6 160.0
real 0m3.394s # <--- 3 second sleep
user 0m0.000s
sys 0m0.015s
回到前提。不要使用四个“脚本”,而是像我上面的
somescript.R
一样重写您的脚本文件。如果正确完成,它们可以像
Rscript
一样运行,也可以用不同的意图进行
source
。
我将使用这个脚本四次,而不是四个脚本。以下是我们想要自动化的手动运行过程:
tasks <- list(
callr::r_bg(somefunc, args = list(5)),
callr::r_bg(somefunc, args = list(1)),
callr::r_bg(somefunc, args = list(10)),
callr::r_bg(somefunc, args = list(3))
)
sapply(tasks, function(tk) tk$is_alive())
sapply(tasks, function(tk) tk$is_alive())
sapply(tasks, function(tk) tk$is_alive())
tasks[[1]]$get_result()
我们可以用编程自动化实现这个。
source("somescript.R")
message(Sys.time(), " starting")
tasks <- list(
callr::r_bg(somefunc, args = list(5)),
callr::r_bg(somefunc, args = list(1)),
callr::r_bg(somefunc, args = list(10)),
callr::r_bg(somefunc, args = list(3))
)
while (any(sapply(tasks, function(tk) tk$is_alive()))) {
message(Sys.time(), " still waiting")
Sys.sleep(1)
}
message(Sys.time(), " done!")
results <- lapply(tasks, function(tk) tk$get_result())
str(results)
现在运行你的第五个函数/脚本。
jobRunScript
运行的作业不会影响(例如存储结果在)调用环境。前四个作业是否将它们的结果保存在外部(例如文件或数据库)? - r2evansjobRunScript()
?哦,我明白了,它是rstudioapi::jobRunScript()
。 - HenrikB