6.3 KiB
Introduction to Python: HTTP (Flask)
So far, we've learnt Python fundamentals, worked with data, files and
more importantly, basic data structures like csv
and json
.
JSON is a very popular format for now only storing, but transporting data in web HTTP applications.
One application could make a web request to ask for customer data from our application. By sending back JSON, the receiving application can easily process the data it gets.
Python Dev Environment
The same as Part 1, we start with a dockerfile where we declare our version of python
.
FROM python:3.9.6-alpine3.13 as dev
WORKDIR /work
Let's build and start our container:
cd python\introduction\part-4.http
docker build --target dev . -t python
docker run -it -v ${PWD}:/work python sh
/work # python --version
Python 3.9.6
Our application
Firstly we have to import our dependencies
import os.path
import csv
import json
Then we have a class to define what a customer looks like:
class Customer:
def __init__(self, c="",f="",l=""):
self.customerID = c
self.firstName = f
self.lastName = l
def fullName(self):
return self.firstName + " " + self.lastName
Then we need a function which returns our customers:
def getCustomers():
if os.path.isfile("customers.json"):
with open('customers.json', newline='') as customerFile:
data = customerFile.read()
customers = json.loads(data)
return customers
else:
return {}
Here is a function to return a specific customer:
def getCustomer(customerID):
customer = getCustomers()
return customer[customerID]
And finally a function for updating our customers:
def updateCustomers(customers):
with open('customers.json', 'w', newline='') as customerFile:
customerJSON = json.dumps(customers)
customerFile.write(customerJSON)
Now to recap and test our functions we need to define a list of customers to use:
customers = {
"a": Customer("a","James", "Baker"),
"b": Customer("b", "Jonathan", "D"),
"c": Customer("c", "Aleem", "Janmohamed"),
"d": Customer("d", "Ivo", "Galic"),
"e": Customer("e", "Joel", "Griffiths"),
"f": Customer("f", "Michael", "Spinks"),
"g": Customer("g", "Victor", "Savkov"),
"h" : Customer("h", "Marcel", "Dempers")
}
Now to convert our customer dictionary to JSON, we need to convert our dictionary of customer objects to a dictionary of customers where each customer is a dictionary instead of a class.
To do this we generate a new dictionary and populate it by converting each customer object to a dictionary :
customerDict = {}
for id in customers:
customerDict[id] = customers[id].__dict__
Then we can finally test our update and get functionality:
updateCustomers(customerDict)
customers = getCustomers()
print(customers)
Let's test it and see the customers.json
file stored to our server and
retrieved.
python src/app.py
External Libraries
JSON Library
Python provides a library for dealing with JSON.
Let's take our customer dictionary, and convert it to json structure and
finally write it to file using our update function.
import json
Now first things first, we need to convert our customers dictionary to a JSON structured string so we can store it to file.
The json
library allows us to convert dictionaries to files using
the dumps
function:
jsonData = json.dumps(customers)
print(jsonData)
But if we run this we get an error:
TypeError: Object of type Customer is not JSON serializable
That is because the library can only deal with full dictionaries. Taking a closer look at our dictionary, our customer is a class.
# our key is a string
# our value is a class
"h" : Customer("h", "Marcel", "Dempers")
json.dumps()
only allows full dictionaries so we need our customer object to be in dictionary form like so:
"h": { "customerID": "h", "firstName" : "Marcel", "lastName" : "Dempers"}
To fix our dictionary, we can iterate it and build a new one
# start with an empty one
customerDict = {}
#populate our new dictionary
for id in customers:
customerDict[id] = customers[id].__dict__
#print it
print(customerDict)
Now we can convert our customer dictionary to json
customerJSON = json.dumps(customerDict)
print(customerJSON)
Now we've converted our data into JSON, we can view this in a new tab window and change the language mode to JSON to visualise the data in our new format.
Now essentially our application will use dictionaries when working with the data
but store and transport it as JSON.
Therefore our update function should take a dictionary and convert it to JSON and store it.
def updateCustomers(customer):
with open('customers.json', 'w', newline='') as customerFile:
customerJSON = json.dumps(customer)
customerFile.write(customerJSON)
We also need to change our getCustomers
function to read the JSON file
and convert that data correctly back to a dictionary for processing.
def getCustomers():
if os.path.isfile("customers.json"):
with open('customers.json', newline='') as customerFile:
data = customerFile.read()
customers = json.loads(data)
return customers
else:
return {}
Finally let's test our functions :
customers = getCustomers()
print(customers)
It's also very easy to add a customer to our JSON data using our class and using pythons internal __dict__
property to convert the object to a dictionary and add it to our customers dictionary
customers["i"] = Customer("i", "Bob", "Smith").__dict__
updateCustomers(customers)
Docker
Let's build our container image and run it while mounting our customer file
Our final dockerfile
FROM python:3.9.6-alpine3.13 as dev
WORKDIR /work
FROM dev as runtime
COPY ./src/ /app
ENTRYPOINT [ "python", "/app/app.py" ]
Build and run our container.
Notice the customers.json
file gets created if it does not exist.
cd python\introduction\part-3.json
docker build . -t customer-app
docker run -v ${PWD}:/work -w /work customer-app