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

Basics

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

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

Supports

  • structured (particulary procedural)
  • oo
  • functional

It has a large Standard Library

PyPy is a just in time compiler

CPython is the standard implementation

venv

https://www.youtube.com/watch?v=W–_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

arepl

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('https://randomuser.me/api/?results=10')

data = response.json()

for user in data['results']:
	print(user['name']['first'])

Pylance

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

print(foo)

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

Kite AutoComplete AI

https://www.kite.com/

VS Code Autodoc string

autoDocString


gh - goto hover docs

then

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

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

    Returns:
        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

Recap

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 main.py

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(requests.__version__)

print("numpy module version:")
print(np.__version__)

response = requests.get('https://httpbin.org/ip')
print('Your IP is {0}'.format(response.json()['origin']))

x = requests.get('https://w3schools.com/python/demopage.htm')
print(x.text)

# 3.6.9 when run with python3 
print("Python intepreter version:")
print(sys.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": "auto_archive.py",
			"console": "integratedTerminal",
			"justMyCode": true,
			"args": ["--sheet","Test Hashing"]
		},
		{
			"name": "Python: Current File",
			"type": "python",
			"request": "launch",
			"program": "${file}",
			"console": "integratedTerminal",
			"justMyCode": true
		}
	]
}
# foo.py
# 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__':
    functionA()
    functionB()
print("after __name__ guard")