9

随着mclapply()所有发出的警告似乎被压制:

library(multicore) 
mclapply(1:3, function(x) warning(x))
[[1]]
[1] "1"

[[2]]
[1] "2"

[[3]]
[1] "3"

虽然lapply会给:

lapply(1:3, function(x) warning(x))
[[1]]
[1] "1"

[[2]]
[1] "2"

[[3]]
[1] "3"

Warning messages:
1: In FUN(1:3[[3L]], ...) : 1
2: In FUN(1:3[[3L]], ...) : 2
3: In FUN(1:3[[3L]], ...) : 3

关于如何避免丢失警告的任何提示?

4

3 回答 3

4

根据mclapply的帮助页面,我认为该参数mc.silent应该允许您选择是否要打印警告。奇怪的是,它没有这样做。明确设置它TRUEFALSE对您的情况没有任何影响。

所以这给我们留下了一个有点肮脏的hack:强制R在警告发生时打印它们。

options(warn=1)
mclapply(1:3, function(x) warning(x))

# Warning in FUN(1L[[1L]], ...) : 1
# Warning in FUN(2L[[1L]], ...) : 2
# Warning in FUN(3L[[1L]], ...) : 3
# [[1]]
# [1] "1"
#
# [[2]]
# [1] "2"
#
# [[3]]
# [1] "3"
于 2014-02-01T11:22:40.077 回答
2

我也遇到了这个问题。如果我正确阅读代码,请将选项parallel::mclapply()传递给. 但是有这条线:mc.silentparallel:mcparallel()mcparallel()

sendMaster(try(eval(expr, env), silent = TRUE))

我认为这是将警告发送回主进程的地方,但mc.silent不被尊重。这是我对正在发生的事情的最佳猜测。

于 2015-10-30T01:30:04.100 回答
1

对于遇到相同问题的任何人,这里有一个解决方法:

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我认为有用的字符表示,因为它给出了消息来自哪里的想法
  • tryCatcharoundwithCallingHandlers有助于优雅地返回错误,从而不影响核心的其他结果
  • 执行后mclapply,打印错误结果的索引
  • stop.on.error提供一个选项来忽略任何包含错误的结果并继续尽管有错误

旁注:我个人更喜欢pbmcapplypbmclapply功能,而不是添加进度条的功能。您可以在上面的代码中更改为。mclapplymclapplypbmclapply

测试代码的小片段:

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)

于 2020-08-12T08:48:33.603 回答