-
Couldn't load subscription status.
- Fork 347
How notebook debug cell works
Notebook cell debugging is similar to how python debugging works. However it uses a DebugAdapter instead of just a DebugAdapterDescriptor.
There's a number of classes involved. This sequence diagram describes how they interact:

These different steps are described in detail below:
The first step is the user clicking the 'Debug cell' button.
The command handler then generates a launch.json entry that looks something like so:
{
type: "Python Kernel Debug Adapter",
name: "mynotebook.ipynb"
request: 'attach',
justMyCode: true,
__mode: "debugCell",
__cellIndex: 2
};where
- the type relates to a registered DebugAdapterDescriptorFactory that generates DebugAdapterInlineImplementation objects.
- it attaches to the kernel
- it has extra properties indicating which cell and whether or not it's debug cell or run by line.
The debugging manager then creates a DebuggingManager with this configuration.
The DebuggingManager just starts debugging with the configuration. This switches VS code into debug mode.
Because a DebugAdapterDescriptorFactory was registered and its type was passed in the launch config, VS code will then attempt to create a DebugAdapterDescriptor.
The KernelDebugAdapter is created as a result of this call and passed as the implementation to the [DebugAdapterInlineImplementation] https://code.visualstudio.com/api/references/vscode-api#DebugAdapterInlineImplementation
The KernelDebugAdapter is an in memory server that is supposed to listen to DAP messages. For more information on handling DAP messages, see the description of Python debugging.
The KernelDebugAdapter is shared between cell debugging and run by line, the only difference being the controller. The controllers job is to intercept certain messages from VS code (and certain responses from debugpy) to force the behavior necessary for the mode it is in. For the DebugCellController, this means behaving just like ordinary python debugging.
After the KernelDebugAdapter and DebugCellController are created, the DebugAdapterInlineImplementation is returned to VS code. It will now use it to send all DAP messages to control the debug session.
The first DAP message is Initialize.
The KernelDebugAdapter's handleMessage is called with the contents of the Initialize message.
The KernelDebugAdapter then parses the contents of the message and translates the cell URI's in it to the expected file name paths debugpy will be seeing in IPython.
How does it know the file paths? IPython has a new special message - dumpCell. This takes the contents of a cell and generates a temporary file for it. That temporary file is used as the translated file path.
The Initialize message is then sent to IPython by making the jupyter [requestDebug](https://jupyter-client.readthedocs.io/en/latest/messaging.html#debug-request) call.
Now you might wonder did IPython implement its own debugger?
No, it actually loads debugpy into itself and forwards DAP requests to debugpy.
Events from debugpy come back on the IO pub channel.
- 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