2013-06-17 3 views
1

Что лучше всего было обрабатывать ошибки в R? Я хочу уметь как отследить трассировки стека от конечного пользователя моего сценария, так и очистить любые временные переменные и состояние, с которым я могу работать.Как элегантно обрабатывать ошибки в R, когда нужно очистить состояние?

Так я полагаю, мой вопрос заключается в два раза:

  1. Самое главное, как я правильно обрабатывать очистки состояния при обработке ошибок?
  2. Как извлечь, полезную, приятную информацию из сообщений об ошибках R, без внутренних вещей, которые выплевывают?

На данный момент у меня есть что-то похожее, но (1) кажется ужасно неэлегантным, и (2) все еще дает мне ужасные сообщения об ошибках.

# Create some temporary working state and variables to clean up 
file <- "somefile" 
working.dir <- getwd() 
setwd("../") # Go somewhere else 
saf.default <- getOption("stringsAsFactors") 
options(stringsAsFactors = FALSE) 

# Now lets try to open the file, but it doesn't work (for whatever reason) 
# I want to clean up the state, stop, and wrap the error string with a nicer 
# message 
tryCatch({ 
    # Need to embed the tryCatch because we still need some of the state variables 
    # for the error message 
    tryCatch({ 
    f <- read.table(file) 
    }, error = function(err.msg) { 
    # Can't clean up here, we still need the `file variable! 
    stop("Could not open file '", file, "' with error message:\n", print(err.msg), 
     call.=FALSE) 
    }) 
}, error = function(err.msg) { 
    # Now we can clean up state 
    setwd(working.dir) 
    options(stringsAsFactors = saf.default) 
    rm(file, working.dir, saf.default, 
    envir=globalenv()) # This also seems awful? 
    stop(print(err.msg), call.=FALSE) 
}) 

# Do more stuff, get more state, handle errors, then clean up. 
# I.e can't use `finally` in previous tryCatch! 

Сообщение об ошибке из этого выходит как, все еще много некрасивых внутренностей:

# <simpleError in file(file, "rt"): cannot open the connection> 
# <simpleError: Could not open file 'somefile' with error message: 
# Error in file(file, "rt"): cannot open the connection 
> 
# Error: Could not open file 'somefile' with error message: 
# Error in file(file, "rt"): cannot open the connection 
# In addition: Warning messages: 
# 1: In file(file, "rt") : 
# cannot open file 'somefile': No such file or directory 
# 2: In stop(print(err.msg), call. = FALSE) : 
# additional arguments ignored in stop() 
> 

ответ

2

Я бы изолировать любое государство меняющийся код на свою собственную функцию, и использовать on.exit. Это гарантирует, что очистка произойдет, независимо от ошибки.

readFile <- function(.....) 
{ 
    on.exit({ 
     setwd(cur.dir) 
     options(stringsAsFactors=saf) 
    }) 
    cur.dir <- getwd() 
    saf <- getOption("stringsAsFactors") 
    setwd("new/dir") 
    options(stringsAsFactors=FALSE) 
    .... 
} 
+0

Возможно ли вырастить список вещей, которые должны произойти при выходе, когда мой сценарий прогрессирует? –

+1

Да, но это сложно. Я просто поставил все необходимые заявления в начале. Если ваш код содержит огромное количество изменений состояния, вероятно, стоит спросить, можно ли его переписать. Например, в вашем случае использования ни одно из имени файла, текущего каталога или параметра 'stringsAsFactors' не должно рассматриваться как состояние. –

+0

Обычно я согласен, но, к сожалению, я пишу один большой сценарий анализа, который, похоже, не подходит для модуляции. Я до сих пор не нашел хорошего решения для работы с ними в воспроизводимом скрипте. На данный момент решение, с которым я работаю, включает в себя завершение всего скрипта в функции и вызов его в том же исходном файле. Таким образом, я не остаюсь с временными переменными при выходе, и я могу свести к минимуму состояние, которое нужно изменить обратно (в настоящее время 'stringsAsFactors' и текущий каталог, потому что он делает последующие вызовы для открытия файлов намного короче). –

Смежные вопросы