Traceback() для интерактивных и неинтерактивных сеансов R

Я наблюдал другое между интерактивным и не-взаимодействующим сеансом R около traceback(), который я не понимаю. В приведенном ниже коде это приведет к ошибке, но в интерактивном сеансе R я могу увидеть информацию о трассировке, тогда как если я сохраню код до test.R и вызову его через Rscript test.R или R -f test.R, я не могу более длинный просмотр traceback:

f = function() {
  on.exit(traceback())
  1 + 'a'
}
f()

В интерактивном сеансе R:

> f = function() {
+   on.exit(traceback())
+   1 + 'a'
+ }
> f()
Error in 1 + "a" : non-numeric argument to binary operator
1: f()

Неинтерактивное выполнение:

$ Rscript test.R 
Error in 1 + "a" : non-numeric argument to binary operator
Calls: f
No traceback available 
Execution halted

Я не видел объяснений в ?traceback, и мне интересно, есть ли способ включить трассировку для неинтерактивных сеансов R. Спасибо!

Ответ 1

Со значениями по умолчанию для своих аргументов traceback() будет искать объект с именем .Traceback в baseenv() для информации о стеке вызовов. Он выглядит (от src/main/errors.c), как .Traceback, создается только в том случае, если среди прочих условий R_Interactive || haveHandler, предполагая, что этот объект не создается во время неинтерактивных сеансов. Если нет объекта с именем .Traceback, вы получите сообщение "Нет возможности отслеживания".

Однако, передав значение non-NULL аргументу x traceback(), можно получить информацию о стеке вызовов из неинтерактивного сеанса. С ненулевым целочисленным значением (с указанием количества вызовов, которые нужно пропустить в стеке) вызываются функции c-level (R_GetTraceback), чтобы исследовать стек вызовов вместо поиска в .Traceback.

Итак, есть несколько способов получить информацию о трассировке в неинтерактивном сеансе:

f = function() {
  on.exit(traceback(1))
  1 + 'a'
}
f()

Или, установив options, как предложил Брэндон Бертельсен

options(error=function()traceback(2))

Различные значения, переданные в x в двух примерах, учитывают различное количество функций для пропуска

  • В примере on.exit traceback(1) пропускает вызов traceback().

  • В примере установки options есть дополнительная анонимная функция, которая вызывает traceback(), которая должна/также быть пропущена.

В примере в OP не так много информации получено при использовании traceback() по сравнению с автоматической трассировкой, предоставленной в случае ошибки в неинтерактивном сеансе. Однако с функциями, которые принимают (и передаются) аргументы, использование traceback() будет гораздо более информативным, чем стандартное представление стека вызовов в неинтерактивном сеансе.

Ответ 2

Существует также возможность отлаживать отладочную информацию и загружать ее позже. (См. Полезные справочные страницы ?debugger и комментарии по теме)

через, например:

options(error = quote(dump.frames("testdump", TRUE)))

...

load("testdump.rda")
debugger(testdump)

или

options(error = quote({dump.frames(to.file = TRUE); q(status = 1)}))