2016-07-06 107 views
0

我想使用tryCatch()來檢查是否在循環中安裝了包,然後返回next以分解並跳到下一次迭代如果程序包未能加載或安裝,則返回循環。同時,我想向控制檯返回一條消息,報告此情況。我可以做一個,也可以做另一個,但我很難找出如何在同一時間做到這一點。例如,這項工作:返回'next'並從tryCatch函數中打印消息以跳到下一個循環迭代

package_list<-c("ggplot2", "grid", "plyr") 

for(p in package_list){ 

    # check if package can't be loaded 
    if(!require(p,character.only=TRUE,quietly=TRUE,warn.conflicts=FALSE)){ 

    write(paste0("Attempting to install package: ",p), stderr()) 

    # try to install & load the packages, give a message upon failure 
    tryCatch(install.packages(p,repos="http://cran.rstudio.com/"), 
      warning = function(e){write(paste0("Failed to install pacakge: ", p), stderr())}, 
      error = function(e){write(paste0("Failed to install pacakge: ", p), stderr())}) 
    tryCatch(library(p,character.only=TRUE,verbose=FALSE), 
      warning = function(e){write(paste0("Failed to install pacakge: ", p), stderr())}, 
      error = function(e){write(paste0("Failed to install pacakge: ", p), stderr())}) 

    # try to install & load the packages, skip to next loop iteration upon failure 
    tryCatch(install.packages(p,repos="http://cran.rstudio.com/"),warning = next) 
    tryCatch(library(p,character.only=TRUE,verbose=FALSE),warning = next) 
    } 
} 

但是這需要運行每個命令兩次;一次失敗並返回關於失敗的消息,然後再次失敗並跳到循環中的下一個項目。

相反,我更願意用單一功能執行這兩個操作,像這樣:

for(p in package_list){ 
    if(!require(p,character.only=TRUE,quietly=TRUE,warn.conflicts=FALSE)){ 
    tryCatch(install.packages(p,repos="http://cran.rstudio.com/"), 
      warning = function(e){print(paste("Install failed for package: ", p)); return(next)}) 
    # ... 
    } 
} 

然而,這種失敗,因爲你不能在函數中使用next來自:

Error in value[[3L]](cond) : no loop for break/next, jumping to top level 

是有兩種方法可以返回所需的消息,併發出next命令從tryCatch()以執行此功能?

回答

1

使用message()而不是write(..., stderr());它需要幾個參數,不需要paste()在一起。

使用tryCatch()返回一個狀態碼,並作用於狀態碼;以下

for (i in 1:10) { 
    status <- tryCatch({ 
     if (i < 5) warning("i < 5") 
     if (i > 8) stop("i > 8") 
     0L 
    }, error=function(e) { 
     message(i, ": ", conditionMessage(e)) 
     1L 
    }, warning=function(w) { 
     message(i, ": ", conditionMessage(w)) 
     2L 
    }) 
    if (status != 0L) 
     next 
    message("success") 
} 

打印

1: i < 5 
2: i < 5 
3: i < 5 
4: i < 5 
success 
success 
success 
success 
9: i > 8 
10: i > 8