-
Notifications
You must be signed in to change notification settings - Fork 325
How interactive debugging works (old way)
The Interactive Window is used for running cells in a python script. One of the capabilities of running these cells is to debug them.
This page will describe how this debugging is implemented under the covers.
This sequence diagram is explained below:
The first step is to inject debugpy into kernel. Without knowing what the process id of the kernel is, we need a way to have the kernel ready for attach. We do this by running this code in the kernel:
import debugpy
debugpy.listen(('localhost', 0))
That causes debugpy to start a server and returns the port to listen on. We use this port to generate a launch config. Something that looks like so:
{
"type": "python",
"request": "attach",
"connect": { "host": "localhost", "port": 5678 },
"justMyCode": true
},
The launch config generated in the previous step is used to attach the debugger to the running debugpy server (much like done here for launching debugging of a python file).
VS code then transitions to debug mode. It just sits there waiting for an event from the debuggee.
The next step is called out as 'Replace kernel's run cell handler'.
What is that code doing? It's replacing the IPython runcell method with a new one so that we can set an environment variable BEFORE we run a cell.
Specifically this code here:
predicted_name = __VSCODE_compute_hash(args[1], args[0].execution_count)
os.environ["IPYKERNEL_CELL_NAME"] = predicted_name
Internally IPython uses the environment variable IPYKERNEL_CELL_NAME
to set the name of the pseudo file associated with any code that's run.
If we need an environment variable to be set when running a cell, why not just execute some code in the kernel? This diagram might explain why:
If we're using cells to change the environment variable, those cells themselves end up with the IPYKERNEL_CELL_NAME
set for them. In the example above, if CELL_2 calls into code in CELL_1, the debugger won't know that it was the original cell 1, and not the second "cell 1" where the variable was set.
To work around this problem, we instead patch the kernel so it sets the variable itself as it executes code.
- Contribution
- Source Code Organization
- Coding Standards
- Profiling
- Coding Guidelines
- Component Governance
- Writing tests
- Kernels
- Intellisense
- Debugging
- IPyWidgets
- Extensibility
- Module Dependencies
- Errors thrown
- Jupyter API
- Variable fetching
- Import / Export
- React Webviews: Variable Viewer, Data Viewer, and Plot Viewer
- FAQ
- Kernel Crashes
- Jupyter issues in the Python Interactive Window or Notebook Editor
- Finding the code that is causing high CPU load in production
- How to install extensions from VSIX when using Remote VS Code
- How to connect to a jupyter server for running code in vscode.dev
- Jupyter Kernels and the Jupyter Extension