У меня работало определение глобальной опции R для обработки некатастрофических ошибок, а также настраиваемый рабочий процесс для сохранения информации об ошибке и проверки этой информации после сбоя. В настоящее время я использую версию R 3.4.1.
Ниже я включил описание рабочего процесса, который работал для меня, а также некоторый код, который я использовал для установки опции глобальной обработки ошибок в R.
Как я настроил, обработка ошибок также создает файл RData, содержащий все объекты в рабочей памяти на момент возникновения ошибки. Этот дамп может быть считан обратно в R с использованием load()
, а затем в интерактивном режиме можно проверить различные среды, существовавшие на момент ошибки, с помощью debugger(errorDump)
.
Замечу, что мне удалось получить номера строк в выводе traceback()
из любых пользовательских функций в стеке, но только если я использовал опцию keep.source=TRUE
при вызове source()
для любых пользовательских функций, используемых в моем скрипт. Без этой опции установка опции глобальной обработки ошибок, как показано ниже, отправляла полный вывод traceback()
в журнал ошибок с именем error.log
, но номера строк были недоступны.
Вот основные шаги, которые я предпринял в своем рабочем процессе, и как я смог получить доступ к дампу памяти и журналу ошибок после неинтерактивного сбоя R.
Я поместил следующее в начало основного сценария, который я вызывал из командной строки. Это устанавливает глобальную опцию обработки ошибок для сеанса R. Мой основной сценарий назывался myMainScript.R
. Различные строки в коде имеют комментарии после них, описывающие, что они делают. По сути, с этой опцией, когда R встречает ошибку, которая вызывает stop()
, он создает файл дампа RData (* .rda) рабочей памяти во всех активных средах в каталоге ~/myUsername/directoryForDump
, а также записывает журнал ошибок с именем error.log
с некоторой полезной информацией в том же каталоге. Вы можете изменить этот фрагмент, чтобы добавить другую обработку при ошибке (например, добавить временную метку в файл дампа и имена файлов журнала ошибок и т. Д.).
options(error = quote({
setwd('~/myUsername/directoryForDump'); # Set working directory where you want the dump to go, since dump.frames() doesn't seem to accept absolute file paths.
dump.frames("errorDump", to.file=TRUE, include.GlobalEnv=TRUE); # First dump to file; this dump is not accessible by the R session.
sink(file="error.log"); # Specify sink file to redirect all output.
dump.frames(); # Dump again to be able to retrieve error message and write to error log; this dump is accessible by the R session since not dumped to file.
cat(attr(last.dump,"error.message")); # Print error message to file, along with simplified stack trace.
cat('\nTraceback:');
cat('\n');
traceback(2); # Print full traceback of function calls with all parameters. The 2 passed to traceback omits the outermost two function calls.
sink();
q()}))
Убедитесь, что из основного скрипта и любых последующих вызовов функций, каждый раз, когда функция вызывается, используется опция keep.source=TRUE
. То есть для источника функции вы должны использовать source('~/path/to/myFunction.R', keep.source=TRUE)
. Это необходимо для вывода traceback()
, содержащего номера строк. Похоже, вы также можете установить эту опцию глобально, используя options( keep.source=TRUE )
, но я не проверял это, чтобы проверить, работает ли она. Если вам не нужны номера строк, вы можете опустить эту опцию.
- Из терминала (вне R) вызовите основной скрипт в пакетном режиме, используя
Rscript myMainScript.R
. Это запускает новый неинтерактивный R-сеанс и запускает скрипт myMainScript.R
. Фрагмент кода, приведенный на шаге 1, который был помещен вверху myMainScript.R
, устанавливает параметр обработки ошибок для неинтерактивного сеанса R.
- Обнаружена ошибка где-то при выполнении
myMainScript.R
. Это может быть в самом основном скрипте, или вложение нескольких функций вглубь. При обнаружении ошибки обработка будет выполняться, как указано в шаге 1, и сеанс R будет прерван.
- Файл дампа RData с именем
errorDump.rda
и журнал ошибок с именем error.log
создаются в каталоге, указанном '~/myUsername/directoryForDump'
в настройке параметра глобальной обработки ошибок.
На досуге осмотрите error.log
, чтобы просмотреть информацию об ошибке, включая само сообщение об ошибке и полную трассировку стека, ведущую к ошибке. Вот пример журнала, который генерируется при ошибке; обратите внимание, что цифры после символа #
являются номерами строк ошибки в различных точках стека вызовов:
Error in callNonExistFunc() : could not find function "callNonExistFunc"
Calls: test_multi_commodity_flow_cmd -> getExtendedConfigDF -> extendConfigDF
Traceback:
3: extendConfigDF(info_df, data_dir = user_dir, dlevel = dlevel) at test_multi_commodity_flow.R#304
2: getExtendedConfigDF(config_file_path, out_dir, dlevel) at test_multi_commodity_flow.R#352
1: test_multi_commodity_flow_cmd(config_file_path = config_file_path,
spot_file_path = spot_file_path, forward_file_path = forward_file_path,
data_dir = "../", user_dir = "Output", sim_type = "spot",
sim_scheme = "shape", sim_gran = "hourly", sim_adjust = "raw",
nsim = 5, start_date = "2017-07-01", end_date = "2017-12-31",
compute_averages = opt$compute_averages, compute_shapes = opt$compute_shapes,
overwrite = opt$overwrite, nmonths = opt$nmonths, forward_regime = opt$fregime,
ltfv_ratio = opt$ltfv_ratio, method = opt$method, dlevel = 0)
На досуге вы можете загрузить errorDump.rda
в интерактивный R-сеанс, используя load('~/path/to/errorDump.rda')
. После загрузки вызовите debugger(errorDump)
, чтобы просмотреть все объекты R в памяти в любой из активных сред. Для получения дополнительной информации см. Справку R на debugger()
.
Этот рабочий процесс чрезвычайно полезен при запуске R в некоторой производственной среде, где у вас неинтерактивные R-сеансы, инициируемые в командной строке, и вы хотите сохранить информацию о непредвиденных ошибках. Возможность выгрузки памяти в файл, который вы можете использовать для проверки рабочей памяти во время ошибки, наряду с наличием номеров строк ошибки в стеке вызовов, способствует быстрой посмертной отладке того, что вызвало ошибку.