Skip to content

Setting up a new Windows laptop for Python development

The Backstory

I've been doing a bit more development on my personal laptop lately and I was starting to brush up against the limits of my hardware. I have a Thinkpad X270, and although it comes with the renowned keyboard and a sturdy (not quite) bullet-proof chassis, I was starting to question the other parts of the spec... 8GB of RAM, an Intel i5-62000U processor and only 155GB of usable disk... I quickly ran out of space after setting up Windows Subsystem for Linux, a few versions of Python and some virtual environments.

Fair enough, I had a bit of bloat that I could slim down but I didn't want to have to make this a regular occurrence. Also, being a bit of a tab whore I was starting to experience a bit of slowness as I switched contexts between VS Code and my browser. Frankly, I could do with an upgrade. And although it had absolutely zero influence over this decision I was also experiencing a few ping issues when playing Age of Empires II: Definitive Edition online despite good ping and speeds on the internet tests... nope, no sway at all.

ping speeds
Wireless speeds... musn't grumble

Although I was tempted by some new shiny models, I didn't want to break the bank. And although Macs are touted for development, I will forever be a Windows child - I just can't seem to break through my frustrations with the Apple UX. Plus, with Windows Subsystem for Linux now a thing and Windows 11 actually looking quite sleek I didn't feel the need to finally get over my Macphobia. If I had the money, (I think it would be funny...🎵), I would have probably went for a souped up Dell XPS 15 after seeing some pretty solid reviews. It seemed to offer good performance for programming and creative workloads while also having a decent graphics card.

As it happens, I spotted a refurbed model of the XPS 15 (9570) on ebay which was packing a 1TB SSD and 32GB of RAM for just shy of £500. This model seemed to review pretty well at the time, and I was happy with this spec at the price point so I decided to purchase. I'm not very tuned in to the world of CPU processors, but it came with an i7-8750H which, while not world-leading, seems to offer a considerable improvement over the i5-62000U of my Thinkpad. And on top of that it came equipped with a Nvidia GTX 1050Ti 4GB graphics card, so if Age of Empires did happen to fire up then I should have fewer online teammates complaining about my lag...

Setup Goals

So it arrived and on unboxing first thoughts were it's a bit chunkier, but then I'm intending to use it mainly as a desktop, and I'll probably hang on to the Thinkpad for a more portable work machine anyway.

We're getting onto why I actually wanted to write this post, and that's to run through my development setup on a new Windows machine, mainly so that when I have to go through this again I have a good point to start from, but also to hopefully demonstrate some good practices for creating a productive development experience on Windows.

Let me run through a few of my main goals:

  1. Using WSL2 for my main development environment

    Linux is probably the most common build environment when building applications, and as such, it makes sense to develop in Linux if we can. Windows Subsystem for Linux offers an awesome way to run a Linux environment on Windows without a virtual machine. It's pretty simple to do and it automatically mounts your Windows drive. The WSL extension for VS Code is going to provide a seamless development experience between the Windows and Linux environments.

  2. Using virtual environments where possible to keep my base installs unpolluted

    This should make libraries/tools easy to purge or upgrade and to prevent any base installations from getting corrupted. I also want to keep project environments separate, and only install what I need to with as few duplicate installs as necessary.

    Two great tools for this in Python are pyenv, which allows for easy installation and switching between different Python versions, and pipx, which installs CLI tools in their own isolated virtual environments, puts all the shims in one place and adds this location to your path so you can use these tools anywhere.

  3. Using the command-line and package managers

    The aim is to automate much of this in the future by putting a bunch of commands into a script, so using the command-line is a must. I also want to make use of some useful package managers:

    • chocolatey (choco) / scoop / winget for Windows
    • apt for Linux (Debian/Ubuntu) and also Homebrew (brew) (yes it works on Linux too)
  4. Making my config dotfiles portable

    As developers, over time we gather a considerable amount of configurations that once we get used to it becomes really difficult to live without. I want a way to make these easily portable to new machines so that even if I'm SSH-ing into a machine on the cloud I can get the development environment that's going to enable me to be most productive.

Anyway, enough goal-setting, let's get cracking...

The Setup

Installing WSL

First on my list is installing WSL. This can take a few hours so it's best to get started with early. Open Powershell with admin privileges and type in the following command:

wsl --install

That easy! The default OS installed for me was Ubuntu 22.04. Leave that to brew while we move onto some of our Windows installs.

Setting up on Windows

While writing this guide (mostly to myself), I ended up diving a bit into Windows package managers and which would be the most suitable. I've spun this out into a separate post so that I can keep this page focused on actual installation steps. But my conclusions were:

  • use scoop for any Windows dev tools and a first port of call for other apps
  • use winget for Microsoft products e.g. OneDrive, OneNote, etc.
  • use choco as a back up for apps that aren't available in scoop e.g. Docker Desktop

So here we go on the Windows steps:

Updating Powershell to latest version

In Powershell with admin privileges:

winget install --id Microsoft.Powershell --source winget

Install Microsoft Apps with winget

In Powershell with admin privileges:

winget install Microsoft.OneDrive --accept-source-agreements --accept-package-agreements
winget install onenote --accept-source-agreements --accept-package-agreements

Note

Adding the arguments --accept-source-agreements --accept-package-agreements results in less confirmations needed in the shell. Use if you're happy with it.

Installing Chocolatey

In Powershell with admin privileges:

Set-ExecutionPolicy AllSigned; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))

Confirm the prompts as necessary (trying to figure out a way to skip these temporarily). You should now have Chocolatey installed, you can check by running choco from the command line.

Warning

The install guide says to inspect their install.ps1 script before running, even though they take security seriously. Personally, I'm happy to go ahead with it and I'm not quite sure what I'm looking for anyway.

Installing scoop

In the scoop docs, it says to install from a Powershell terminal with the following:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression

However, I was getting a few issues with the execution policy - this seemed to work instead:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls
$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
[System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols

irm get.scoop.sh | iex

This issues may be down to the version of Powershell I was on when initially installing scoop but this remains uninvestigated - just need something that works.

Installing some apps with scoop

I just wanted to touch briefly on a few apps installed here.

Particularly for develepment I'm installing:

  • git as my version control system
  • pyenv so that I can install multiple Python versions in isolated environments and easily switch between them. scoop will install pyenv-win since it is an installer for Windows.
  • VS Code as my main IDE
  • Oh My Posh which offers nice prompt customisation.

Installing a couple of chat tools:

  • Slack: some developer communities are on here.
  • Element: same here - I've been communicating with the dyanconf maintainers here recently on some recent contributions.

And then I've just got Firefox as my browser, Obsidian which is a note-taking app I am experimenting with a little. And Steam, because... well...

In any shell (doesn't need to be admin):

scoop update
scoop install git
scoop install pyenv
scoop install https://github.com/JanDeDobbeleer/oh-my-posh/releases/latest/download/oh-my-posh.json
scoop bucket add extras
scoop install vscode
reg import "C:\Users\User\scoop\apps\vscode\current\install-context.reg"
reg import "C:\Users\User\scoop\apps\vscode\current\install-associations.reg"
# I think the following 3 are in extras too, since they have GUIs.
scoop install screentogif
scoop install obsidian
scoop install element
scoop install slack
scoop install firefox
scoop bucket add games
scoop install steam

Installing some apps with Chocolatey

There were a couple of apps that I struggled to install via scoop:

  • Docker Desktop: this is another developer tool for pulling and running containers, which happens to integrate very nicely with WSL.
  • Discord: another chat app with developer communities, plus I use this to chat to my rage buddies.

You can install docker with scoop since it's just a CLI tool, but I wanted the Desktop GUI too. For some reason it's not in the extras bucket but that's fine, it's why I have choco as backup.

Discord is available on scoop, but for some reason when I installed it via scoop Windows Defender seemed to think it was a trojan. Sounds like I should be panicking huh? But a quick search seemed to identify it as a known false flag - panic over?. Anyway, I just decided to use choco for this rather than investigate further.

In Powershell with admin privileges:

choco install docker-desktop
choco install discord

Note

If you don't want to confirm Y/N for each install, you can switch this off in choco global config with choco feature enable -n=allowGlobalConfirmation.

Installing Python

As noted in my setup goals the plan is to have WSL as my main development environment, but it will still be useful to have at least one version of Python installed on the Windows path. I'll use pyenv to install it.

In any shell (doesn't need to be admin):

pyenv update # (2)!
# Install the latest Python version
latest_py=$(pyenv install --list | grep -v '[a-z]' | tail -1) # (1)!
pyenv install $latest_py
pyenv global $latest_py # (3)!
  1. This will grab the latest stable Python release.
  2. Make sure pyenv is up-to-date with current versions.
  3. Once installed we'll set this version as the global default.

Setting up VS Code

This is quite easy with VS Code's settings sync feature which I'd switched on and linked to my GitHub account on my old PC. All I had to do was log in and all of my configurations, extensions and keybindings were ported like magic.

settings sync

This guide is already getting quite long so I won't get into the specifics of my VS Code setup just yet, maybe another time...

Setting up on Linux (WSL)

I've put up a separate post covering how I've setup my WSL development environment in a portable way. It's definitely worth checking out!

Extras

Make sure Docker Desktop configured to WSL

Make sure this setting is checked within Docker Desktop to use with WSL. This should make the Docker CLI available in WSL while Docker Desktop is up and running.

Docker WSL backend

Custom terminal prompts with Oh-My-Posh

Oh My Posh brings a nice pop of colour to the terminal with a variety of themes to choose from. Check out all of the fully customisable themes here.

Installing with scoop...
scoop install https://github.com/JanDeDobbeleer/oh-my-posh/releases/latest/download/oh-my-posh.json
$env:Path += ";C:\Users\user\AppData\Local\Programs\oh-my-posh\bin"

Many of the prompt themes make use of iconography which requires you to have a Nerd Font installed. Oh My Posh provides a nice tool to install the one you want:

oh-my-posh font install FiraCode

Because I want to configure the Nerd Fonts for Windows Terminal (which WSL launches in on Windows 11) and Visual Studio Code, I think I need the fonts installed on Windows rather than Linux. I installed in both though just to be sure:

oh-my-posh font install Hack

I had a bit of trouble configuring the VS Code font for a while, I think because I didn't have "Mono" in the font name. Anyway, here's the two settings that I've configured for the 'Hack' Nerd Font:

Windows Terminal settings.json
    "profiles":
    {
        "defaults": {
            "font":
            {
                "face": "Hack Nerd Font Mono"
            }
        },
        ...
    }
VS Code settings.json
  "terminal.integrated.fontFamily": "'Hack Nerd Font Mono'",

And with the font configured (only for nushell currently):

oh-my-posh prompt

I've configured for Monty's theme here. You can also check out my other nu config in the custom.nu file there if you're interested.

Wrap Up

So there you have it, my setup for Python development and beyond on my new Windows 11 laptop. It's been a bit of a beast doing all of it and capturing in writing but I hope you (and my future self) gets something useful from it.

I may come back and make some new additions to this from time-to-time as I integrate more into my workflow, but this is more than enough for now.


Which parts of this guide will you try and integrate into your own environment?

Comments