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