对于遇到相同问题的任何人,这里有一个解决方法:
safe_mclapply <- function(X, FUN, mc.cores, stop.on.error=T, ...){
fun <- function(x){
res_inner <- tryCatch({
withCallingHandlers(
expr = {
FUN(x, ...)
},
warning = function(e) {
message_parallel(trimws(paste0("WARNING [element ", x,"]: ", e)))
# this line is required to continue FUN execution after the warning
invokeRestart("muffleWarning")
},
error = function(e) {
message_parallel(trimws(paste0("ERROR [element ", x,"]: ", e)))
}
)},
error = function(e){
# error is returned gracefully; other results of this core won't be affected
return(e)
}
)
return(res_inner)
}
res <- mclapply(X, fun, mc.cores=mc.cores)
failed <- sapply(res, inherits, what = "error")
if (any(failed == T)){
error_indices <- paste0(which(failed == T), collapse=", ")
error_traces <- paste0(lapply(res[which(failed == T)], function(x) x$message), collapse="\n\n")
error_message <- sprintf("Elements with following indices failed with an error: %s. Error messages: \n\n%s",
error_indices,
error_traces)
if (stop.on.error)
stop(error_message)
else
warning(error_message, "\n\n### Errors will be ignored ###")
}
return(res[!failed])
}
#' Function which prints a message using shell echo; useful for printing messages from inside mclapply when running in Rstudio
message_parallel <- function(...){
system(sprintf('echo "\n%s\n"', paste0(..., collapse="")))
}
safe_mclapply
上面是一个包装器mclapply
。对于每次迭代,它用于withCallingHandlers
捕获和打印警告和错误;请注意,这invokeRestart("muffleWarning")
是继续执行FUN
并返回结果所必需的。打印是通过message_parallel
使用 shellecho
将消息打印到 R 控制台的函数完成的(经过测试可以在 Rstudio 中工作)。
safe_mclapply
提供了一些您可能会发现可选的功能:
- 连同警告和错误,它会打印
x
我认为有用的字符表示,因为它给出了消息来自哪里的想法
tryCatch
aroundwithCallingHandlers
有助于优雅地返回错误,从而不影响核心的其他结果
- 执行后
mclapply
,打印错误结果的索引
stop.on.error
提供一个选项来忽略任何包含错误的结果并继续尽管有错误
旁注:我个人更喜欢pbmcapply的pbmclapply
功能,而不是添加进度条的功能。您可以在上面的代码中更改为。mclapply
mclapply
pbmclapply
测试代码的小片段:
X <- list(1, 2, 3, 4, 5, 6)
f <- function(x){
if (x == 3){
warning("a warning")
warning("second warning")
}
if (x == 6){
stop("an error")
}
return(x + 1)
}
res <- safe_mclapply(X = X, FUN = f, mc.cores=16)
res_no_stop <- safe_mclapply(X = X, FUN = f, mc.cores=16, stop.on.error = F)