【问题标题】:warnings() does not work within a function? How can one work around this?警告()在函数中不起作用?如何解决这个问题?
【发布时间】:2011-04-30 12:47:07
【问题描述】:
op <- options(warn=0)  #although doesn't work for any value of warn
assign("last.warning", NULL, envir = baseenv())  
thisDoesntWork<- function() {
warning("HEY, this is definitely a warning!")
cat(paste("number of warnings:",length(warnings())))
}   
>thisDoesntWork()
Warning in thisDoesntWork() : HEY, this is definitely a warning!
number of warnings: 0

警告数应为 1 而不是 0 - 如果在函数中调用,warnings() 似乎什么也不返回。为什么?如何解决此问题以检查函数中是否出现警告并将其打印出来?

我不想使用tryCatch,因为那样我会丢失函数返回的值(它可能仍然返回有效值,即使它产生了警告)。

【问题讨论】:

    标签: r error-handling


    【解决方案1】:

    这是suppressWarnings的代码

    function (expr) 
    {
        withCallingHandlers(expr, warning = function(w) invokeRestart("muffleWarning"))
    }
    

    我对其进行了一些调整,以计算警告的数量。

    countWarnings <- function(expr) 
    {
        .number_of_warnings <- 0L
        frame_number <- sys.nframe()
        ans <- withCallingHandlers(expr, warning = function(w) 
        {
          assign(".number_of_warnings", .number_of_warnings + 1L, 
            envir = sys.frame(frame_number))
          invokeRestart("muffleWarning")
        })
        message(paste("No. of warnings thrown:", .number_of_warnings))
        ans
    }
    

    测试:

    countWarnings(log(-1))
    No. of warnings thrown: 1
    [1] NaN
    

    另一个测试:

    foo <- function()
    {
      warning("first warning!")
      warning("second warning!")
      warning("third warning!")
      invisible()
    }
    countWarnings(foo())
    No. of warnings thrown: 3
    NULL
    

    【讨论】:

    • 您可能还想将警告的数量作为答案的属性返回。 attr(ans, "number_of_warnings") &lt;- .number_of_warnings
    • 太棒了!我也可以这样抓取警告信息(w
    【解决方案2】:

    您的示例确实返回警告。

    > assign("last.warning", NULL, envir = baseenv())  
    > thisDoesntWork <- function() {
    +   warning("HEY, this is definitely a warning!")
    +   cat(paste("number of warnings:",length(warnings())),"\n")
    + }
    > thisDoesntWork()
    number of warnings: 0 
    Warning message:
    In thisDoesntWork() : HEY, this is definitely a warning!
    > warnings()  # HEY, here's your warning!!!
    Warning message:
    In thisDoesntWork() : HEY, this is definitely a warning!
    

    文档并不明确,但我认为 last.warning 在调用完成之前不会被设置(特别是考虑到调用是可以返回的一部分)。

    【讨论】:

    • 谢谢,正如您在我看到的那样,它吐出“警告数:0”它在我的机器上不起作用-带有 R 2.11.1 GUI 1.34 Leopard 构建 32 位(5589 )。嗯,我现在应该尝试什么?
    • 查看我的编辑(我忘了清除 last.warning)。我不认为这是特定于平台的。
    • 如果您对 last.warning 直到返回才被设置是正确的,那么我就被卡住了。在函数中,如何确定是否发生了警告,而不会丢失函数返回的值?使用 tryCatch 当然会捕获警告,但如果没有嵌入到 tryCatch 中,似乎会丢失函数返回的值
    • warnings() 的使用与 options('warn') 相关联(读取 ?options),正如 Joshua 所暗示的,它在 REPL 迭代结束时设置。当我最近清理 rApache 的错误日志代码时,我发现了这一点。解决方案是将您的代码包装在 tryCatch 中并实现您自己的警告处理程序来计算已发生的处理程序的数量。
    【解决方案3】:

    可能这是一个非常非常糟糕的解决方法......

    fw<-function(){warning("warn...");return(99)}
    fn<-function(){return(88)}
    
    f<-function(){
        w<-0
        v<-NULL
        v<-tryCatch(fw(),warning=function(w){w})
        if("warning"%in%class(v)){
            w<-w+1 # e.g., count up the number of warning
            v<-fw()
        }
        print(v)
    
        v<-NULL
        v<-tryCatch(fn(),warning=function(w){w})
        if("warning"%in%class(v)){
            w<-w+1 # e.g., count up the number of warning
            v<-fn()
        }
        print(v)
    }
    f()
    

    如果出现警告,则调用该函数两次... 虽然我相信一定有更优雅的解决方案

    【讨论】:

    • 是的,我自己刚开始思考这个问题 :) 编写代码既痛苦又不优雅
    【解决方案4】:

    这里有一个解决方法

    ..my_warning <- 0L
    
    thisDoesWork<- function(){
        assign("last.warning", NULL, envir = baseenv())  
        warning("HEY, this is definitely a warning!", {..my_warning <<- ..my_warning+1L;""})
        str(last.warning)
        cat(paste("number of warnings:", ..my_warning, "\n"))
    }
    
    
    thisDoesWork()
    Warning in thisDoesWork() : HEY, this is definitely a warning!
    NULL
    number of warnings: 1 
    >     thisDoesWork()
    Warning in thisDoesWork() : HEY, this is definitely a warning!
    NULL
    number of warnings: 2 
    >     thisDoesWork()
    Warning in thisDoesWork() : HEY, this is definitely a warning!
    NULL
    number of warnings: 3 
    > 
    

    【讨论】:

    • 是的 - 一个杂牌,但老实说,我经常使用&lt;&lt;- :)
    • 另一种方法是使用选项。在任何情况下都需要某种“全局性”。
    【解决方案5】:

    警告不会在函数返回之前发出。 请参阅有关选项(“警告”)的文档:

    options(warn=1L)
    thisDoesntWork()
    #Warning in thisDoesntWork() : HEY, this is definitely a warning!
    #number of warnings: 1 
    

    【讨论】:

    • 和第一个回答的人一样,我想你可能忘记先调用assign("last.warning", NULL, envir = baseenv())。如果是这样,则该函数找到的 1 个警告来自先前的调用..
    • 这对我来说似乎是一个错误。我会在 r-devel 上报告。
    猜你喜欢
    • 2021-05-03
    • 2014-01-28
    • 1970-01-01
    • 1970-01-01
    • 2020-10-24
    • 1970-01-01
    • 2016-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多