In previous Python articles I’ve

  • Setup Python 3.8, 3.9, 3.10 using deadsnakes PPA on Ubuntu
  • Used pipenv as a virtual environment
  • Explored importing modules (Standard lib, 3rd party, app specific)
  • Debugging using VSCode to a specific virtual environment
  • Debugging to a specific file always run
  • There is no entry point so use name guard


Python is 31 years old (20th Feb 1991 appeared). WikiPedia

  • emphasises readbility using indentation
  • dynamically typed
  • garbage-collected


  • structured (particulary procedural)
  • oo
  • functional

It has a large Standard Library

PyPy is a just in time compiler

CPython is the standard implementation

venv–_EOzdTHk&t=67s Traversy Media setting up VS Code for Python (Feb 2020)

He is using venv instead of pipenv.

sudo apt install python3.9-venv
# could have used pip to install instead (some may say after installing pip with apt I should do this)
pip install virtualenv

# python3.9-venv/bionic,now 3.9.12-1+bionic1 amd64 [installed]
apt list --installed | grep venv

python3.9 -m venv venv

# vscode will run this automatically if it detects venv when you start a new terminal
source ./venv/bin/activate

pip install <some-package>

So this is simpler that pipenv in that I have to do pip installs myself


alt text

Auto evaluates in real time - wow real time running of code!

File doesn’t need to be saved for it to auto evaluate.

# source ./venv/bin/activate
# pip install requests
import requests

response = requests.get('')

data = response.json()

for user in data['results']:


ms implementation

Euler 1

Solving the problem with the repl was great as could see results immediately

# If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
# Find the sum of all the multiples of 3 or 5 below 1000.

i = 1
foo = 0
while i < 1000:
    if (i % 3 == 0):
        foo += i
    elif (i % 5 == 0):
        foo += i
    i += 1


And now lets try a more functional approach

alt text

Notice the tabs at the bottom, and spaces near the top. Ah!

alt text

Fixed - using 4 spaces now (the default). When I press tab it puts in 4 spaces.


Kite AutoComplete AI

VS Code Autodoc string


gh - goto hover docs


# function taking 2 strings and returning a string
# three " to get autodoc to work
def greet(greeting, name):
    """Returns a Greeting

        greeting (string): A greet word 
        name (string): A Persons name

        string: A greeting 
    return f'{greeting}, {name}'

print(greet('hello', 'world'))

Testing with PyTest

alt text

settings, test, enable pytest

pip install pytest

Python test explorer too

def add(x,y):
	return x +y

def test_add():
	assert add(1,2) == 3


python3.8 -V

sudo add-apt-repository ppa:deadsnakes/ppa -y

sudo apt install python3.9 -y

apt list --installed | grep python

export PATH=/home/dave/.local/bin:$PATH

sudo apt install python3-pip -y
pip install --upgrade pip

pip install --user pipenv

cd project-folder

# create Pipfile and Pipfile.lock if not there
# gets all dependencies if an existing project (or need to update)
pipenv install

# this may use 3.8
pipenv install requests

# specific version
#pipenv --python 3.9 install requests

pipenv install numpy

# activate the shell!
pipenv shell

# run inside the virtual env
pipenv run python

Python program I used to print the version of the module I was using, and the Python interpreter version.

# If running in non-virtual don't need to import this module 2.22.0 is there already (comes with Ubuntu as apt python3-requests)
# latest is 2.27.1
import requests
import sys
# we do need to import numpy
import numpy as np

print("requests module version:")

print("numpy module version:")

response = requests.get('')
print('Your IP is {0}'.format(response.json()['origin']))

x = requests.get('')

# 3.6.9 when run with python3 
print("Python intepreter version:")

Debugger working in 3.9 on VSCode

Here is my .vsocde/launch.json specificing which file should enter/start debugging with (very useful if have anohter file open and don’t want to start with that). Also passing the default arguments to.

	"version": "0.2.0",
	"configurations": [
			"name": "Python: auto_archive --sheet",
			"type": "python",
			"request": "launch",
			"program": "",
			"console": "integratedTerminal",
			"justMyCode": true,
			"args": ["--sheet","Test Hashing"]
			"name": "Python: Current File",
			"type": "python",
			"request": "launch",
			"program": "${file}",
			"console": "integratedTerminal",
			"justMyCode": true
# all code at indentation level 0 gets executed
# there is no implicit main() function
print("before import")
import math

print("before functionA")
def functionA():
    print("Function A")

print("before functionB")
def functionB():
    print("Function B {}".format(math.sqrt(100)))

# Python interpreter defines a few special variables.. we care about __name__ here.
# which is the name of the file being executed
# if we import foo from another module, it wont fire
print("before __name__ guard")
if __name__ == '__main__':
print("after __name__ guard")