我不知道这对您当前的场景有多大的适应性,但这里有一种方法可以让四个东西并行运行,获取它们的返回值,然后触发第五个表达式/函数。
前提是使用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) {
# put the contents of a script file in this function, and have
# it return() the data you need back in the calling environment
Sys.sleep(seconds)
return(mtcars[sample(nrow(mtcars),2),1:3])
}
if (sys.nframe() == 0L) {
# if we're here, the script is being Rscript'd, not source'd
somefunc(3)
}
作为演示,如果source'd 在控制台上,这个只是定义了函数(或多个,如果你愿意),它不会执行最后一个if内的代码块:
system.time(source("~/StackOverflow/14182669/somescript.R"))
# # <--- no output, it did not return a sample from mtcars
# user system elapsed
# 0 0 0 # <--- no time passed
但如果我在终端中使用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。如果操作正确,它们可以是 Rscripted 以及 sourced,具有不同的意图。
我将使用这个脚本四次而不是四个脚本。这是我们想要自动化的手动运行:
# library(callr)
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())
# [1] TRUE FALSE TRUE FALSE
### time passes
sapply(tasks, function(tk) tk$is_alive())
# [1] FALSE FALSE TRUE FALSE
sapply(tasks, function(tk) tk$is_alive())
# [1] FALSE FALSE FALSE FALSE
tasks[[1]]$get_result()
# mpg cyl disp hp drat wt qsec vs am gear carb
# Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
# Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
我们可以使用
source("somescript.R")
message(Sys.time(), " starting")
# 2020-08-28 07:45:31 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))
)
# some reasonable time-between-checks
while (any(sapply(tasks, function(tk) tk$is_alive()))) {
message(Sys.time(), " still waiting")
Sys.sleep(1) # <-- over to you for a reasonable poll interval
}
# 2020-08-28 07:45:32 still waiting
# 2020-08-28 07:45:33 still waiting
# 2020-08-28 07:45:34 still waiting
# 2020-08-28 07:45:35 still waiting
# 2020-08-28 07:45:36 still waiting
# 2020-08-28 07:45:37 still waiting
# 2020-08-28 07:45:38 still waiting
# 2020-08-28 07:45:39 still waiting
# 2020-08-28 07:45:40 still waiting
# 2020-08-28 07:45:41 still waiting
message(Sys.time(), " done!")
# 2020-08-28 07:45:43 done!
results <- lapply(tasks, function(tk) tk$get_result())
str(results)
# List of 4
# $ :'data.frame': 2 obs. of 3 variables:
# ..$ mpg : num [1:2] 24.4 32.4
# ..$ cyl : num [1:2] 4 4
# ..$ disp: num [1:2] 146.7 78.7
# $ :'data.frame': 2 obs. of 3 variables:
# ..$ mpg : num [1:2] 30.4 14.3
# ..$ cyl : num [1:2] 4 8
# ..$ disp: num [1:2] 95.1 360
# $ :'data.frame': 2 obs. of 3 variables:
# ..$ mpg : num [1:2] 15.2 15.8
# ..$ cyl : num [1:2] 8 8
# ..$ disp: num [1:2] 276 351
# $ :'data.frame': 2 obs. of 3 variables:
# ..$ mpg : num [1:2] 14.3 15.2
# ..$ cyl : num [1:2] 8 8
# ..$ disp: num [1:2] 360 304
现在运行你的第五个函数/脚本。