2016-06-29 17 views
11

Einige Debugger ermöglichen das dynamische Hinzufügen von Haltepunkten im Debugger. Ist diese Funktionalität in R möglich? Ein Beispiel:Trace/Breakpoint hinzufügen, während sie bereits im Browser von R vorhanden sind

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" 

Beim Debuggen glaube ich, ich möchte im Code voraus springen. Stellen Sie sich vor, die Funktion hat ein paar hundert Zeilen Code, und ich würde es vorziehen, sie nicht zu durchlaufen.

Ich würde gerne in der Lage sein, dies zu tun, und von der aktuellen Zeile zur nächsten interessanten Zeile springen, aber leider geht es einfach aus der Funktion.

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

Der trace Anruf, während nur im Debugger den Haltepunkt auf die ursprüngliche (global) Funktion, wie gezeigt hinzugefügt, wenn ich die Funktion sofort wieder anrufen:

quux() 
# Tracing quux() step 5 
# Called from: eval(expr, envir, enclos) 
# Browse[1]> 
# debug: [1] "line 5" 

Ich habe versucht, beide auf einmal einstellen (at=c(3,5)) im Browser, aber das setzt nur die Zeilen, wenn ich den Debugger verlasse und die Funktion erneut aufruft.

Ich vermute, das hat mit der Funktion zu tun, an die trace den Haltepunkt anbringt. Ein Blick in trace (und .TraceWithMethods), ich denke, ich muss where einstellen, aber ich kann nicht herausfinden, wie man es bekommt, um einen neuen Haltepunkt/Trace auf der In-Debugging-Funktion zu setzen.

(Das größere Bild ist, dass ich eine Funktion, die sich mit einem Kafka-geführten Datenstrom beschäftigt. Meine beiden Optionen sind derzeit (a) starten Sie die Funktion mit der geeigneteren Ablaufverfolgung, aber das erfordert mich zu tun Bereinigen und starten Sie den Datenstrom ebenfalls neu oder (b) gehen Sie zeilenweise im Debugger, langwierig, wenn es viele hundert Zeilen Code gibt.)

+2

Ich vermute, dass dies nicht direkt möglich ist, da die Ablaufverfolgung/Debugging-Mechanismen neue Funktionen mit aktiviertem Debuggen erstellen. Was Sie möglicherweise tun können, ist, wenn die Zeile, zu der Sie springen möchten, selbst ein Funktionsaufruf ist, dann debuggen Sie diese Funktion. z.B. In '{line1; line2; line3; my_fun(); line4}' können Sie 'debug (my_fun)' gefolgt von 'c' an der Browse-Eingabeaufforderung ausführen und direkt zum Inhalt' my_fun' springen. – BrodieG

+1

Danke, das ist was ich vermute. Ihr Vorschlag funktioniert, wenn am nächsten Haltepunkt eine Funktion vorhanden ist. Danke, @ BrodieG. – r2evans

Antwort

1

Dies kann eine Art Lösung sein. Zuerst tun, wie in Ihrem Beitrag:

> 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" 

Als nächst wir tun, wie im Debugger folgt:

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" 

Der Nachteil ist, dass wir bei "line 5" im ursprünglichen Aufruf quux nachdem wir Austrittsende wieder aus der Anruf an this_func. Außerdem müssen wir den letzten -Wert im Auge behalten. Vielleicht können wir das von einer anderen Funktion bekommen?

+0

Sehr interessant, danke Benjamin! Ich werde damit ein bisschen herumspielen. – r2evans

+0

Froh zu helfen, wenn diese Antwort Ihr Problem gelöst hat, bitte markieren Sie es als akzeptiert. –

+0

Ist es auch ein Nachteil, dass hier die ersten * n * Codezeilen erneut ausgeführt werden? Wenn beispielsweise irgendeine der ersten Zeilen irgendwelche Nebeneffekte (z. B. Datenbankaktualisierungen) enthält, wäre dies keine praktikable Option. Ich finde es immer noch interessant, danke Benjamin. – r2evans