Добавить трассировку/точку останова, находясь в браузере R
Редактировать: для записи принятый ответ имеет существенный недостаток в том, что он повторно выполняет первые n строк кода в функции при повторной отладке. Это может быть хорошо, но когда эти строки кода включают побочные эффекты (например, обновления базы данных) и/или длительные вычисления, становится очевидным, что происходит. Я не верю, что R предоставляет возможность делать это "правильно" (как это делают некоторые другие языки). Облом.
Некоторые отладчики позволяют динамически добавлять точки останова, находясь в отладчике. Возможна ли эта функциональность в R? Пример:
quux <- function(..)
{ # line 1
"line 2"
"line 3"
"line 4"
"line 5"
"line 6"
}
trace("quux", tracer = browser, at = 3)
# [1] "quux"
quux()
# Tracing quux() step 3
# Called from: eval(expr, envir, enclos)
# Browse[1]>
# debug: [1] "line 3"
Во время отладки я верю, что хочу ускорить выполнение кода. Представьте, что функция имеет несколько сотен строк кода, и я предпочел бы не проходить через них.
Я хотел бы иметь возможность сделать это и перейти от текущей строки к следующей интересной строке, но, к сожалению, она просто выходит из функции.
# Browse[2]>
trace("quux", tracer = browser, at = 5)
# [1] "quux"
# Browse[2]>
c
# [1] "line 6"
# # (out of the debugger)
Вызов trace
в отладчике просто добавил точку останова к исходной (глобальной) функции, как показано, если я немедленно вызову функцию снова:
quux()
# Tracing quux() step 5
# Called from: eval(expr, envir, enclos)
# Browse[1]>
# debug: [1] "line 5"
Я попытался установить оба сразу (at=c(3,5)
) в браузере, но это просто устанавливает эти строки, когда я выхожу из отладчика и снова вызываю функцию.
Я предполагаю, что это связано с функцией, к которой trace
прикрепляет точку останова. Рассматривая trace
(и .TraceWithMethods
), я думаю, что мне нужно установить where
, но я не могу понять, как заставить его установить новую точку останова/трассировки в функции отладки.
(Более общая картина состоит в том, что я устраняю неисправность функции, имеющей дело с потоком данных под руководством Кафки. В настоящее время у меня есть два варианта: (а) перезапустить функцию с более подходящей трассировкой, но это требует от меня очистки и перезапуска поток данных, а также (b) построчно переходить в отладчик, утомительно, когда в коде много сотен строк.)
Ответы
Ответ 1
Это может быть своего рода решение. Сначала сделайте так, как в своем посте:
> quux <- function(..)
+ { # line 1
+ x <- 1 # added for illustration
+ "line 3"
+ "line 4"
+ "line 5"
+ print(x) # added for illustration
+ "line 7"
+ "line 8"
+ }
>
> trace("quux", tracer = browser, at = 4)
[1] "quux"
> quux()
Tracing quux() step 4
Called from: eval(expr, p)
Browse[1]> n
debug: [1] "line 4"
Далее в отладчике мы делаем следующее:
Browse[2]> this_func <- eval(match.call()[[1]]) # find out which funcion is called
Browse[2]> formals(this_func) <- list() # remove arguments
Browse[2]> body(this_func) <- body(this_func)[-(2:4)] # remove lines we have evalutaed
Browse[2]> trace("this_func", tracer = browser,
+ at = 8 - 4 + 1) # at new line - old trace point
Tracing function "this_func" in package "base"
[1] "this_func"
Browse[2]> this_func # print for illustration
function ()
{
"line 5"
print(x)
"line 7"
"line 8"
}
Browse[2]> environment(this_func) <- environment() # change enviroment so x is present
Browse[2]> this_func() # call this_func
[1] 1
[1] "line 8"
Недостатком является то, что мы вернемся к "line 5"
в исходном вызове quux
после выхода из вызова this_func
. Кроме того, мы должны отслеживать последнее значение at
. Мы можем получить это от другой функции?