5 steps to Python, VS Code & WSL2
9 min read

5 steps to Python, VS Code & WSL2

5 steps to Python, VS Code & WSL2

Python is widely regarded as being one of the easier languages to get started with. A lot of this is due to the relatively uncluttered formatting that relies on whitespace rather than brackets. However easy or difficult you may find the language itself though, there is one barrier to starting with Python that a lot of people stumble over: setting up your environment.

My personal development setup

  • All (well, almost all) development done on a PC using Linux on WSL2
  • Python installed within WSL2
  • "Core" Python tools installed using pipx
  • A virtual environment created for each project using pipenv
  • VS Code as an IDE with some useful extensions installed
  • Docker installed and configured for use within the WSL environments
  • Git for version control (I use both Github and Gitlab)

This is, of course, all personal preference, but I thought it might be useful to run through exactly how I would set up a "fresh" system.


Why do I do it like this? Well, some of it is personal preference, but the main reason is that the vast majority of target systems where you will want to deploy anything will be Linux. Developing on Linux right from the start will hopefully make this a smoother process from start to finish.

1. Set up Windows Subsystem for Linux (WSL2)

There are already excellent instructions for setting up WSL2 on Windows on the Microsoft site: https://docs.microsoft.com/en-us/windows/wsl/install-win10

Ubuntu is the usual choice to get working on, but Debian and OpenSuse are also available for free, and there are other distributions such as CentOS that you can pay for in the Microsoft store. Pick whatever you are comfortable with, and if you're not sure, stick with Ubuntu for the moment.

Beyond that, there are extra things I have set up, but which aren't necessary to just get Python working from a WSL2 Linux distribution.


2. Install Python in WSL2

Before installing anything new, make sure that everything else is up to date.

sudo apt update && upgrade

That done, you can install Python.

sudo apt install python3 python3-pip

Note that different distributions use different package managers. apt will work for Ubuntu and Debian. OpenSUSE uses zypper.

And that's it. At least that's enough to get you going. If you want to start playing with multiple installs of different Python versions, then read the next bit. Otherwise, feel free to skip that - you have enough set up already to get you going.

Managing multiple versions of Python

There is no issue with having multiple versions installed, although one of them will need to be the default version for the system.
To check if you do have multiple versions installed already:

$ update-alternatives --list python

If this command instead returns information that:

update-alternatives: error: no alternatives for python

there are 2 options: either you don't have Python installed, or you haven't told update-alternatives about the versions you do have.

It is important to note that update-alternatives does not automatically detect everything you install in the system and work out whether the installs are a different version of a package already installed. That would be a mammoth task!

If, for some reason, I needed to install Python 3.7 as well - perhaps to work on a specific project that used it. I would first install the 3.7 version to the system, and then tell update-alternatives about it.

update-alternatives --install /usr/bin/python python /usr/bin/python3.7 3
update-alternatives: using /usr/bin/python3.7 to provide /usr/bin/python (python) in auto mode

The 3 in the command line there refers to the priority. update-alternatives then allows you to change which version is the default.

$ update-alternatives --config python
There are 2 choices for the alternative python (providing /usr/bin/python).

  Selection    Path                Priority   Status
  0            /usr/bin/python3.9   2         auto mode
* 1            /usr/bin/python3.8   1         manual mode
  2            /usr/bin/python3.9   2         manual mode

Press <enter> to keep the current choice[*], or type selection number:

You can then select the Python version you want to set as default. Note that it may be necessary to run this command as sudo. If you run it without sudo privileges, and see this message:

update-alternatives: error: error creating symbolic link '/etc/alternatives/python.dpkg-tmp': Permission denied

then simply run sudo !!, enter the root password you used when installing that Linux distro in WSL, and try again.

sudo !! is a handy *nix command that simply re-runs the previous command with sudo privileges, to save you retyping the entire command.

To see which version you are currently using, it will not be possinle to use which python, as this will now point to a generic python file.

$ which python

Instead, just make sure to use python --version, which will always return the correct information.

$ python --version
Python 3.9.0+

3. Set up core Python packages

Pretty much every bit of advice you read about handling Python packages tells you not to install packages into your core system, and insted use a virtual environment. But what about packages you want to use from your core system?

There's one single package I install after a fresh python install, and one only: [pipx](https://pypi.org/project/pipx/).

This then allows you to pipx install otherpackage, and it will create an isolated virtual environment containing just that package. Packages installed in this way will not show up with pip list. Instead pipx list is required.

Once this is installed, I pipx install the following packages:

  • pipenv - a virtual environment manager for projects
  • black - an opinionated code formatter I use with everything. You should too, simply because it saves you worrying about what your code should look like.
  • flake8 - a linting tool.
  • ipython - an interactive python shell that is much more feature rich than the standard python REPL.

Most languages come packaged with a REPL when you install them, and Python is no exception. REPL stands for Read, Evaluate, Print, Loop, and allows you to run commands directly from your terminal. It can be a very useful tool when you want to test out some code without having to create files or fire up your IDE.

Once this is done, you should see something like this:

$ pipx list
venvs are in /home/mike/.local/pipx/venvs
apps are exposed on your $PATH at /home/mike/.local/bin
   package black 20.8b1, Python 3.8.5
    - black
    - black-primer
    - blackd
   package flake8 3.8.4, Python 3.8.5
    - flake8
   package ipython 7.19.0, Python 3.8.5
    - iptest
    - iptest3
    - ipython
    - ipython3
   package pipenv 2020.11.15, Python 3.8.5
    - pipenv
    - pipenv-resolver
    - virtualenv
    - virtualenv-clone

These packages can now all be used as though they were installed in your core system, and not nicely hidden away in their own little virtual environments. If you need to clean things up later, it makes life much easier.

4. Set up VS Code


There are a few things that need setting up for VS Code. The basic instructions on the Microsoft site are pretty detailed, but just to sum up

  1. Install VS Code into Windows (not WSL2) first
  2. Make sure wget and ca-certificates are installed in your WSL2 distro of choice.
sudo apt-get install wget ca-certificates
  1. Navigate to a folder you want to open in VS code (doesn't really matter what the first time), and run code .. The necessary packages will be installed to your distro automatically, without you having to worry about it.

That should be it. When you open VS Code like this, you should see an indicator in the bottom left that it is running from a WSL distro.


VS Code extensions

Like any good IDE, VS Code allows you to install extensions, and there are a lot of these in the marketplace. Click on the icon in the left sidebar that looks like this to get to the marketplace.


The first extensions you want to install are:

  • The official Microsoft Python extension
  • Visual Studio IntelliCode

Note that extensions need to be installed inte each environment. So if you have previously installed the Python extension for windows use, you will need to tell VS Code to install it for use from your WSL as well.

Beyond this, go crazy. There are extensions to make your life easier in a myriad of different ways, or just to change the way VS code looks. Here are a few of the ones I have installed that I find helpful:

  • Deepdark Material Theme
  • Docker
  • Bracket Pair Colorizer 2
  • file-icons
  • Git Graph
  • Json Editor
  • Live Server
  • Rainbow CSV
  • Remote - WSL
  • SQLite
    There are loads more that may be useful for the way you work. I suggest you browse around a little and see what works and what doesn't. Just having the main 2 I suggest above should get you going though.

One new one that may be worth mentioning is Pylance, which provides Python language support. I've not had a chance to dig into this too much yet, but I am hearing good things about it.

Settings for tools, linting etc.

Now, remember that we installed things like black and flake8 (or your other linting tools of choice) using pipx. That means these do not sit in the core environment, so we need to tell VS code just where they are.

Clicking on the settings cog in the bottom left of the VS Code window brings you to the settings screen (you can also open this as JSON if you like). You'll notice there are 3 levels:

  • User - Your personal settings applied to everything
  • Environment - Settings for the current environment (i.e. your WSL env)
  • Workspace - Settings for the current project you're working on

I suggest you set up your linting tools at the User level, so they will apply to any Python project you open. To get them working for your pipx installs, you need to find the following config options:

Config setting Value
Flake8 Path pipx path for flake 8
Black Path pipx path for black

These paths will most likely be /home/<your WSL username>/.local/bin/<tool>, but you can verify this by running eg. which black in your WSL distro.

$ which black
$ which flake8

I also stongly sugest you check the Editor: Format on Save checkbox. This will then black your code each time you save it, and save you thinking about how it looks and let you focus on writing code that works.

5. Create a virtual environment for your project

There are 2 common ways these days to create a self-contained environment for your projects:

  • Using a python virtual env tool, eg. pipenv
  • Using Docker

A project may well use both. Going into Docker in too much detail would make this tutorial too long, so we'll mainly cover the python virtual environments here and I'll add a few notes about Docker at the end so you can look into it yourself if you like.

I will stick with pipenv as this is my primary tool, but here are a couple of other options you can look into if you want to use something different.

  • virtualenv
  • venv

If you need a tool that supports a project working on multiple versions of Python (e.g. an open source project), then pipenv may not be your best choice.


To initialise your environment, navigate to your base project directory, and run pipenv install. This will set up a new virtual environment, with no extra packages installed, and you'll see 2 new files created: Pipfile and Pipfile.lock.

Pipfile is pretty easy to read, and you will see that as you install things into your environment they will show up in here.
Pipfile.lock is not something you will normally need to worry about (and perhaps the subject of a future post). It stores hash values for the versions of all installed packages, and is used to make sure there are no conflicts.

What do you want to do? pipenv command
Install a pypi package pipenv install <package>
Install a pypi package I only need during dev pipenv install --dev <package>
I've just moved to my project directory and I need a shell with all the packages installed pipenv shell (--dev)
Update the package version currently installed pipenv update <package>
What else can I do with pipenv? pipenv --help


I won't cover a lot about installing Docker here, as there are plenty of tutorials around that already. Also, if you're a beginner, I'd be inclined to skip Docker entirely for the moment. While it's certainly a useful tool, it will only serve to confuse you if you try and learn multiple things at once.

The only thing I think worth mentioning for the moment, is that if you are using WSL2, then Docker Desktop requires that you specifically configure it to allow access to the WSL2 environments.

This configuration is found in Settings -> Resources -> WSL INTEGRATION, where each WSL disto can be enabled/disabled for Docker.


That's it!

Congratulations! You should now all be set up to start your Python development using a WSL2 Linux distribution on your Windows machine!

Enjoying these posts? Subscribe for more