2-14: Debugging External Scripts (Unfinished)
0.1 To-do
create functions script with embedded if-else statements within for loops
multiple commands on one line?
get into traceback?? mentioned in 2-13
1 Purpose
Use browser() to degub external script
Alternate ways to debug script
Downloading package script and debugging those
2 Material
The script for the lesson is here
A second script that contains a function to debug
The data used for the lesson is here
3 Adding breakpoints to external scripts
In last lesson, we learned how to add breakpoints to a script using the RStudio inteface to add a red dot to the gutter area of the scrtipt. This method works well if you are working in just one script. However, you will likely find yourself wanting to add a breakpoint to a script that is called by your main script. This could either be a functions script or a script from a package. Adding breakpoints to external scripts called from your main script is not quite as simple. In this lesson we will go over the ways to add breakpoints to scripts outside of your main script
4 browser()
The most straightforward way to add a breakpoint is to add the command browser() to the location in your script where you want the breakpoint. browser() acts just like a breakpoint by pausing your script and putting your script in debug mode. We can take examples from the last lesson and replace the breakpoint with browser(). Note: browser() is added to your script and needs to be removed after debugging.
4.1 RStudio breakpoint is an injected browser()
Almost… because RStudio cannot see the injected browser() until after commands have been executed
4.2 add browser to code
We can add browser() to line 7 of the script from last lesson and click Source. You will see the familiar debug features
<image of browser() with green arrow>
4.3 add browser to for loop
Instead of putting a NULL command in a for loop so that a breakpoint can be put on the line, we can put browser(). Don’t forget to remove or comment out browser() when you are done debugging
<link back to last lesson’s NULL in for loops>
<image for loop with two browser() instead of NULL>
5 browser() in function scripts
The main reason to use browser() is that it work in script files outside of script being Sourced. In the script files, we call a second script named < >. This script has functions in used by the main script. Adding breakpoints to the functions script will not work if you Source the main script. However, adding browser() will work.
5.1 Example 1: if
5.2 Example 2: for loop
You do not have editting access to script inside of a package so you cannot easily add browser(). The way around this is to download the package and add it to your library directly.
5.3 Downloading package script
5.4 Including downloaded package scripts
5.5 Modifying downloaded scripts
6 Alternate ways to add breakpoints
6.1 source() outside script first, add breakpoints
do not source() or rm(list=lm()) in main script
only works when Run
6.2 source() from main script, add breakpoints, run function
do not source() or rm(list=lm()) in main script
only works when Run
does it work if you put the bp on the function??
- No, because source()
6.3 add breakpoints, debugSource() from main script, run function
do not source() or rm(list=lm()) in main script
only works when Run
does it work if you put the bp on the function??
- no, it gets really weird!
7 Package scripts
8 Application
code to put a pause in the function ?? in package ??
code to put a pause in the for loop at 10 iteration in function ?? in package ??
code to put a pause in the for loop when x=?? in function ?? in package ??
code to put a pause inside if-if
code to print x every 10th iteration of a for loop
cat each factor
Below here is older ideas that I do not think will be in the class
9 debug() debugonce()
script must be in Environment to debug???
browser() does not work for functions that you cannot edit. In other words, you cannot use browser() to pause a function within a package. If you need to debug a function in a package, then you can use debug() or debugonce(). Both of these function will inject a browser() command to the beginning of a function.
It is easiest to see how debug() works using a function within your script and then apply it to a function from
9.1 debug function script
9.2 undebug
9.3 debugonce
same as before – don’t need to undebug (issue with not undebugging…)
9.4 debug within package
find package function that’s relatively easy to debug
pause is at beginning of script (not convenient)
<pracma package?>
10 trace()
The disadvantage of debug() is that it always pauses at the beginning of a function. That is often not …. If you want to control where the pause is put then you need to use trace(). trace() can be used to inject browser() anywhere in the function. This is done by telling trace() which command inside the function, by number, you want to pause before.
This command would acts just like the debug() above:
<trace, first command>
This command would put the pause on the third command:
<trace, third command>
The number is not the line number, but the command number
11 trace() with loops and if statements
Complete if-else statements and for loops are counted as one command. So, if you want to put a pause after, you need to
<trace, command after for loop>
If you want to put a pause within an if-else statement or for loop, that you need to subset the command number with a second command number
<trace, command in for loop>
<trace, command in if-else statement>
Every time there is an embedded if-else statement or for loop, you need to subset trace()
<trace, command in for loop, in if-else, in for loop>
12 Inject code beyond browser()
trace() can inject any code into your function
<inject cat() in for loop>
<inject if(i==1) { } in for loop>