У меня сработало указание глобальной опции 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 в памяти в любой из активных сред. Для debugger()
получения дополнительной информации см. Справку по R.
Этот рабочий процесс чрезвычайно полезен при запуске R в некоторой производственной среде, где у вас есть неинтерактивные сеансы R, инициируемые из командной строки, и вы хотите, чтобы информация о неожиданных ошибках сохранялась. Возможность делать дамп памяти в файл, который вы можете использовать для проверки рабочей памяти во время ошибки, наряду с номерами строк ошибки в стеке вызовов, облегчает быструю посмертную отладку причины ошибки.