Debugging stride¶
This tutorial is for users and developers that want to debug the stride source code with the
Python debugger. It includes instructions for a UI-based workflow with VSCode native debugging
with pdb.
The tutorial assumes that you have cloned the stride repository with git, are in the root directory of the repository, and have activated your virtual environment.
Debugging with VSCode¶
The stride repository includes a VSCode debug configuration to debug the (1) UI and (2) project
creation process. For setup instructions, please refer to
VSCode instructions.
Select the
Run and Debugbutton on the left side of theVSCodeapplication. The MacOS keyboard shortcut isShift-Cmd-D. The Windows shortcut isShift-Ctrl-D.The
debugmenu will appear at the top of the screen. Next to a green triangle button (for run) is a drop-down where you can select a configuration. ChooseDebug create project.Navigate to the source file
src/stride/project.pyand search fordef create.Set a breakpoint at the first line of the create method.
Warning
Executing the rest of this procedure will overwrite the project at ./test_project
Press the green triangle button to run.
VSCodewill stop execution at that line. You can use theVSCodetools to debug the code.
Debugging with pdb in a terminal¶
pdb is the standard debugger provided by the Python standard library. Please refer to its
instructions for complete information.
Running the stride CLI through pdb requires the location of the stride executable. This
varies based on your operating system and shell.
$ which stride
$ Get-Command stride
$ where stride
The result will be something like:
/Users/dthom/repos/stride/.venv/bin/stride
Running a CLI command then becomes something like this:
$ python -m pdb /Users/dthom/repos/stride/.venv/bin/stride projects create --help
You will see output like this:
> /Users/dthom/repos/stride/.venv/bin/stride(3)<module>()
-> import re
(Pdb)
Press c and enter and then the program will run to completion.
This can be simplified with text substitution in your shell. Here are examples for various shells.
$ python -m pdb $(which stride) projects create --help
$ python -m pdb (Get-Command stride).Path projects create --help
$ for /f "tokens=*" %i in ('where stride') do python -m pdb "%i" projects create --help
Debug any exception that occurs at runtime¶
This is useful to debug unhandled exceptions in the code (bugs). When executed this way, Python
will automatically enter the debugger (pdb) when the exception is raised. Then you can inspect
local variables, move up and down the stack, and run your own code.
$ python -m pdb $(which stride) projects create tests/data/project_input.json5
$ (Get-Command stride).Path projects create tests/data/project_input.json5
$ for /f "tokens=*" %i in ('where stride') do python projects create tests/data/project_input.json5
Set a breakpoint at a specific line number¶
Let’s suppose that you want to debug the projection creation process. You want to
set a breakpoint at the Project.create method entry point.
You can set the breakpoint in the following ways:
Add a call to
breakpoint()at your desired line of code in the source file. Run the CLI command in the normal way.Instruct
pdbto stop at specific function or line number.
These instructions describe the pdb procedure.
Run the command above to create a project.
You will be at this pdb prompt:
> /Users/dthom/repos/stride/.venv/bin/stride(3)<module>()
-> import re
(Pdb)
Import stride, and set a breakpoint at the create method, and then continue execution. Python will stop at the breakpoint.
(Pdb) import stride
(Pdb) b stride.project.Project.create
Breakpoint 1 at /Users/dthom/repos/stride/src/stride/project.py:57
(Pdb) c
> /Users/dthom/repos/stride/src/stride/project.py(77)create()
-> config = ProjectConfig.from_file(config_file)
Enter l and/or ll to see the current context. Press n to execute a line of code.
Press s to step into a function. Print a variable like this:
(Pdb) p config
ProjectConfig(project_id='test_project', creator='tester', description='This is a test project.', country='country_1', start_year=2025, end_year=2055, step_year=5, weather_year=2018, scenarios=[Scenario(name='baseline', energy_intensity=None, gdp=None, hdi=None, load_shapes=None, population=None), Scenario(name='alternate_gdp', energy_intensity=None, gdp=PosixPath('tests/data/alternate_gdp.csv'), hdi=None, load_shapes=None, population=None)], calculated_table_overrides=[])
Pydantic objects like this can can be hard to read. Use the rich library to get a better view.
(Pdb) from rich import print
(Pdb) print(config)
ProjectConfig(
project_id='test_project',
creator='tester',
description='This is a test project.',
country='country_1',
start_year=2025,
end_year=2055,
step_year=5,
weather_year=2018,
scenarios=[
Scenario(name='baseline', energy_intensity=None, gdp=None, hdi=None, load_shapes=None, population=None),
Scenario(
name='alternate_gdp',
energy_intensity=None,
gdp=PosixPath('tests/data/alternate_gdp.csv'),
hdi=None,
load_shapes=None,
population=None
)
],
calculated_table_overrides=[]
)