Что лучше всего было обрабатывать ошибки в R? Я хочу уметь как отследить трассировки стека от конечного пользователя моего сценария, так и очистить любые временные переменные и состояние, с которым я могу работать.Как элегантно обрабатывать ошибки в R, когда нужно очистить состояние?
Так я полагаю, мой вопрос заключается в два раза:
- Самое главное, как я правильно обрабатывать очистки состояния при обработке ошибок?
- Как извлечь, полезную, приятную информацию из сообщений об ошибках 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()
>
Возможно ли вырастить список вещей, которые должны произойти при выходе, когда мой сценарий прогрессирует? –
Да, но это сложно. Я просто поставил все необходимые заявления в начале. Если ваш код содержит огромное количество изменений состояния, вероятно, стоит спросить, можно ли его переписать. Например, в вашем случае использования ни одно из имени файла, текущего каталога или параметра 'stringsAsFactors' не должно рассматриваться как состояние. –
Обычно я согласен, но, к сожалению, я пишу один большой сценарий анализа, который, похоже, не подходит для модуляции. Я до сих пор не нашел хорошего решения для работы с ними в воспроизводимом скрипте. На данный момент решение, с которым я работаю, включает в себя завершение всего скрипта в функции и вызов его в том же исходном файле. Таким образом, я не остаюсь с временными переменными при выходе, и я могу свести к минимуму состояние, которое нужно изменить обратно (в настоящее время 'stringsAsFactors' и текущий каталог, потому что он делает последующие вызовы для открытия файлов намного короче). –