在R'中添加跟踪/断点;s浏览器

在R'中添加跟踪/断点;s浏览器,r,debugging,trace,R,Debugging,Trace,编辑:对于记录,接受的答案有一个显著的下降,因为它在重新调试时重新执行函数中的前n行代码。这可能没问题,但当这些代码行包含副作用(例如,数据库更新)和/或长时间计算时,发生的事情就显而易见了。我不相信R提供了“正确”完成它的能力(就像其他一些语言那样)。糟糕透了 某些调试器允许您在调试器中动态添加断点。这种功能在R中可能实现吗?例如: quux <- function(..) { # line 1 "line 2" "line 3" "line 4" "line 5"

编辑:对于记录,接受的答案有一个显著的下降,因为它在重新调试时重新执行函数中的前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"
在调试器中进行的
跟踪
调用仅将断点添加到原始(全局)函数中,如我立即再次调用该函数所示:

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
,但我不知道如何让它在in-debug函数上设置新的断点/跟踪

# Browse[2]>
trace("quux", tracer = browser, at = 5)
# [1] "quux"
# Browse[2]>
c    
# [1] "line 6"
# # (out of the debugger)

(更大的情况是,我正在对处理kafka led数据流的函数进行故障排除。我的两个选项当前是(a)使用更合适的跟踪重新启动函数,但这需要我清除并重新启动数据流;或(b)在调试器中一行一行地执行,当有数百行代码时会很乏味。)

这可能是一种解决方案。首先,请按照您的帖子中的内容进行操作:

> 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"
quux跟踪(“quux”,tracer=browser,at=4) [1] “quux” >quux() 跟踪quux()步骤4 调用自:eval(expr,p) 浏览[1]>n 调试:[1]“第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"
Browse[2]>此函数形式(this函数)体(this函数)跟踪(“this函数”,tracer=browser,
+at=8-4+1)#新线处-旧跟踪点
在包“base”中跟踪函数“this_func”
[1] “这个函数”
浏览[2]>此功能打印以获取插图
函数()
{
“第5行”
打印(x)
“第7行”
“第8行”
}
浏览[2]>环境(this_func)this_func()#调用this_func
[1] 1
[1] “第8行”

缺点是,在退出对
此函数的调用后,我们回到了对
的原始调用中的
第5行
。此外,我们必须在
值处跟踪最后一个
。我们可能可以从另一个函数中获取此信息?

我怀疑这不可能直接实现,因为跟踪/调试机制依赖于在启用调试的情况下创建新函数。您可以做的是,如果要跳到的行本身就是一个函数调用,则
debug
该函数。e、 g.在
{line1;line2;line3;my_fun();line4}
中,您可以在浏览提示下运行
debug(my_fun)
,然后运行
c
,您将直接跳到
my_fun
的内容。谢谢,这就是我所怀疑的。如果在下一个断点处有函数,则您的建议有效。谢谢,@BrodieG。非常有趣,谢谢本杰明!我将讨论一下这个问题。这是否也是一个缺点,它会重新执行前n行代码?例如,如果前几行中的任何一行包含任何副作用(例如,数据库更新),这将不是一个可行的选项。我仍然觉得这是一个有趣的工作,谢谢本杰明。再次感谢本杰明,终于给了你答案的道具。