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.

“Intellisense”

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 force pylance otherwise things crash.

Interaction with/execution of python

Plain python

One thing I discovered by accident today is that the jupyter support includes a fully interactive python code environment that does not at all require the awful jupyter notebook.

The magic trick is to put the following comment in:

# %%

Now everything after it is one “cell” that I can run with a click. 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.

jupyter

Jupyter notebook support is highly evolved, in that we can run edit and execute them inside VS Code. It is quasi seamless in that the seams are not obvious but upon careful inspection, definitely there.

I am a jupyter skeptic but I have to 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 or the new jupyter lab.

Further, heaps of other things that native jupyter notebooks cannot even dream of just magically work! Remote editing? Easy! Type inference! Autocomplete! Debugger injection! Search and replace across a whole project! Style checking! refactor assistance! Comprehensible documentation.

There are still some broken things (refactoring ignores jupyter notebooks, session sharing broke for me in a weird way last time) but since jupyter notebooks are IMO fundamentally just a bit shit, I will take whatever incremental and patchy support I can get. I imagine that some jupyter notebook extensions don’t work, but since all the extensions I was installing were simply to try and make jupyter behave a little bit more like vs code, they are, AFAICT, redundant.

Refactoring

Somewhat magical, sometimes. TBD.

Debugger

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 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 very powerful feature of the basic python debugger.

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 is silent on the matter and 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 is 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": false,
            "connect": {
                "host": "localhost",
                "port": 25698
            },
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "."
                }
            ]
        },
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal"
        }
    ]
}

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

and 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 this plugin which is now deprecated.

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.