VS Code for python

A quite good python IDE

VS Code support for python is getting pretty good. Here is where I document how, and my preferred configuration.

Interaction with/execution of python

Interactive python

TIL that VS code’s so-called jupyter support includes a fully interactive python code environment that does not require the awful jupyter notebook file-format/interface, but operates plain python modules.

The trick is to put the magic # %% comment in:

# %%
msg = "Hello World"

# %%
msg = "Hello again"

Now everything after that comment is one “cell” that I can run with a click or Ctrl-Enter. NB: that keyboard shortcut to execute the cell sometimes doesn’t work. I do not know why. Plotting is supported too (opens in a side window).

The workflow is suspiciously easy. I have done nothing to deserve this, except to complain about jupyter.

This is a helpful idea. For one thing, it avoids the horrible, bad, no good jupyter file format.

CommandKeyboard shortcut
Python: Go to Next CellCtrl+Alt+]
Python: Go to Previous CellCtrl+Alt+[
Python: Extend Selection by Cell AboveCtrl+Shift+Alt+[
Python: Extend Selection by Cell BelowCtrl+Shift+Alt+]
Python: Move Selected Cells UpCtrl+; U
Python: Move Selected Cells DownCtrl+; D
Python: Insert Cell AboveCtrl+; A
Python: Insert Cell BelowCtrl+; B
Python: Insert Cell Below PositionCtrl+; S
Python: Delete Selected CellsCtrl+; X
Python: Change Cell to CodeCtrl+; C
Python: Change Cell to MarkdownCtrl+; M


Jupyter notebook support is highly evolved, in that we can run edit and execute Jupyter notebooks inside VS Code. If it is not seamless then at least the seams are not too obstructive.

I am a jupyter skeptic but I admit VS Code does sift some of the some of the rougher chunks out of the jupyter grind.

All in all, editing jupyter notebooks is much better than the jupyter notebook browser front end, at least for my workflow, and less jupyter is better jupyter.

Further, heaps of other things that native jupyter notebooks cannot even dream of just magically work! Type inference? Yes! Autocomplete? Sure! Debugger injection? Sometimes! Search and replace across a whole project? Urgh, kinda! Style checking? Yes! Refactor assistance? Yes, and it only fails some random subset of times! Comprehensible documentation for all of these features with a single source of truth? Usually!

There are still some broken things (refactoring ignores jupyter notebooks sometimes, session sharing broke for me in a weird way last time, search is unpredictable, keyboard shortcuts are inconsistent, scrolling to the correct bit of the notebook just fails sometimes) but since jupyter notebooks are IMO irreducibly just a bit shit, I will take whatever incremental and patchy improvement I can get.

I imagine that jupyter notebook extensions don’t work for VS Code but I have not tested this. Essentially all the jupyter extensions I was installing were to make the jupyter notebook interface impersonate VS Code, so I can pay this no mind.

Points of friction: Jupyter Notebook can interact badly with VS code remote, losing data if there is a buggy extension installed. (See also.)


Somewhat magical, sometimes. TBD.


pylance (source) is an extension that works alongside Python in Visual Studio Code to provide performant language support. Under the hood, Pylance is powered by Pyright, Microsoft’s static type checking tool. Using Pyright, Pylance has the ability to supercharge your Python IntelliSense experience with rich type information, helping you write better code faster.

There are other language servers but I have found it advisable to use pylance, otherwise things crash.


VS Code has a rather luxurious multi-language debugger based on a multi-language open debugger protocol which includes support for the python-style debugging. The details are managed by an extension microsoft/debugpy, but users can remain oblivious to that unless doing some ornate remote debugging (for which, see below).

Notable features include visualisation of various python objects, including Pytorch tensors.

Jupyter debugger is cursed

It was not obvious how to use this debugger tool for post-mortem debugging in jupyter notebooks, or, e.g. how to see what led to a crash after the fact, which is a lamented, powerful feature of the basic python debugger unavailable to us in fancy modern jupyter.

tl;dr We cannot quite do that. I need to set the experiment running using the debugger if I want to do a post mortem when it dies.

The manual was silent on the matter; Last time I searched online for “python post mortem debugger jupyter vscode” I was directed to this very page. So I guess the answer needs to go right here.

The answer I found was that I needed to activate the Debugger menu in the sidebar and then check the User uncaught exception option.

Then those tiny buttons next to the Main thread act as step debugger commands.

Useful configs

A launch.json supporting local and remote debugging is this:

    "version": "0.2.0",
    "configurations": [
            "name": "Python: Remote Attach",
            "type": "python",
            "request": "attach",
            "justMyCode": true,    // don't debug libraries
            "stopOnEntry": false,  // don't wait around for me to click "continue"
            "connect": {
                "host": "localhost",
                "port": 25698
            "pathMappings": [
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "."
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "justMyCode": true,    // don't debug libraries
            "stopOnEntry": false   // don't wait around for me to click "continue"

VS code will not automatically construct the tunnel, so we still need do that manually. We can do this the classic way,

ssh remote.server.com -L 25678:localhost:25678

There is a semi-automatic tunnelling tab next to the terminal window in VS code that probably does something similar. Full walk-through here. Hard-coding the values in a launch.json might seem clunky. It is. Here are some people discussing that bulletmark/debugpy-run is a workaround for some dynamic configurations.

NB: there are still some references around to ptvsd, an older version of the python plugin which is now deprecated. Ignore ’em.

Pro-tip: code which uses threading for parallelism can hang in the usual weird ways. Some of these can be ameliorated by invoking with

env PYDEVD_UNBLOCK_THREADS_TIMEOUT=4 python my_script.py

No comments yet. Why not leave one?

GitHub-flavored Markdown & a sane subset of HTML is supported.