Jerry Nordbye
November/26/2018
IT FND 100 B au Oct: Foundations of Programming: Python
Assignment 7
A script to show error handling and Pickling
Introduction
Write a simple
script showing error handling with Pythons try-except and using Pickling to
save and read objects from disk.
Variables
Since
this is a small script we only have a few variables [Figure 1] objFileName
and objFileName2 are used to store the file names we’ll be
using. The two variables for our test lists are lstInventoryDishes and lstInventoryUtensils.
[Figure 1] variable list
Try Except
The try-except
block (Real Python. “Python Exceptions: An Introduction.”) is Pythons way of catching
runtime errors. In its most basic form you put the code that has potential to throw
a run time error in the try part of the
block [Figure2] if a run time error comes up Python will execute what’s in the except block [Figure 2] instead of displaying
the error on the screen and exiting.
[Figure 2] Basic try-except block
You can
trap all errors and treat them as one [Figure 2] or you can trap individual
errors [Figure 3] and treat them accordingly while still having a catch all for
other errors. Figure 3 also demonstrates you can have a try-except block with another
try-except block. In figure 3 we catch the end of file error (EOFError) so we
know we have read all the contents of the file and can continue instead of
Python throwing and error and exiting the script.
[Figure 3] Embedded try-except blocks
The
try-except block can also end with “else” and or “Finally” [Figure 4]. The “else” block is run if there are no exceptions
while the “Finally” block will run whether there is an error or not.
[Figure 4] Try example from https://docs.python.org/3/tutorial/errors.html
[External site]
There are
many individual types of errors you can catch. Here are a few, ZeroDivisionError, FileNotFoundError,
FileExistsError. A nice list can be
found here at airbrake.io https://airbrake.io/blog/python-exception-handling/class-hierarchy
[External site]
Pickling
Pickling
(Pickle - Python Object Serialization.) is a way to store objects in Python to either
a file or over the network. Couple things to watch out for. Pickling is a Python
only thing if you need interoperability with other languages look towards JSON.
Also you can run into issue Pickling data in one version of Python and trying
to read it in another. You can Pickle many types of objects in Python. Below is
a list from Python.org https://docs.python.org/3/library/pickle.html
[External site]
- None, True, and False
- integers, floating point
numbers, complex numbers
- strings, bytes, bytearrays
- tuples, lists, sets, and
dictionaries containing only picklable objects
- functions defined at the top
level of a module (using def, not lambda)
- built-in functions defined at
the top level of a module
- classes that are defined at the
top level of a module
- instances of such classes
whose __dict__ or
the result of calling __getstate__() is
picklable (see section Pickling
Class Instances for details).
You can use Pickling to serialize
and entire object [Figure 5] or the individual elements within an object [Figure
6]. The dump method (pickle.dump()) is used to pickle and save an object. Pickle
dumps arguments are the file object’s name and access mode. The ‘b’ in the access mode argument “wb” stands
for Binary, the file type. The saveInventoryWhole
method saves the entire list as one object where the saveInventoryIndivd method uses the for loop to go thru the list and
then saves each item individually.
[Figure 5] Pickle the entire list as one
[Figure 6] Pickle individual elements of an object
To read the
data back into the program you use the load method (pickle.load()). The load
method takes one argument the file object name and unpickles and returns the
object. Below are two examples of unpickling. The first example loadInventoryWhole method [Figure 7]
loads the entire object which in this case is a list back in a once. Out next
example loadInventoryIndivd method
[Figure 8] needs to loop thru the entire file as we saved each element of the
list individually. We use the EOFError
error to let us know we have reached the end of file. Seems wrong to do it this
way but I have seen lots of examples doing just this and non-doing it any other
way. Also, no complaints were made in regards of this method so it seems it’s
the correct or accepted way of handling
this.
[Figure 7] loadInventoryWhole
[Figure 8] loadInventoryIndivd
Output
Since
this is a very basic script the output is very minimal. The program saves two
lists lstInventoryDishes and lstInventoryUtensils save them to file
Inventory.dat and Inventory2.dat respectively, clears out the list, reloads the list from disk and then prints the
list out to show it did work. I have included a couple screenshots first from PyCharm
[Figure 9] and next from the dos prompt [Figure 10]
[Figure 9] output in PyCharm
[Figure 10] output from Dos command box
Summary
We created
a simple script demonstrating the try-except block and how to both Pickle and
unpickle objects and save them to disk.
Full source code follows the appendix
Appendix
Real Python: “Python Exceptions: An Introduction.” Real
Python, Real Python, 23 July 2018,
realpython.com/python-exceptions/#the-try-and-except-block-handling-exceptions.
The Python Exception Class Hierarchy: Airbrake Blog, 3 Nov. 2017,
airbrake.io/blog/python-exception-handling/class-hierarchy.
Pickle - Python Object Serialization.: 16.2. Threading -
Higher-Level Threading Interface - Python 2.7.15 Documentation,
docs.python.org/2/library/pickle.html.
Source Code
# -------------------------------------------------#
# Title: Exceptions and pickling module
# Dev: JNordbye
# Date: December/3/2018
# ChangeLog: (Who, When, What)
# J Nordbye 12/3/18, Added code to complete assignment 5
#
# -------------------------------------------------#
import pickle #import the pickle Module
#=------------------- Data -----------------------#
objFileName = "Inventory.dat"
objFileName2 = "Inventory2.dat"
lstInventoryDishes = [("Mug", 24.99, 5), ("Cup", 14.99, 10), ("Saucer", 9.99, 10)] # list of items in inventory
lstInventoryUtensils =[("Knife", 9.99, 25), ("Fork", 4.99, 20), ("Spoon", 4.99, 10)] # list of items in inventory
#------------------- Input/Output -------------------#
def listInventory( inInventory): # print out whats in the specifiedInventory
for item in inInventory:
print(f" {item[2]:2} {item[0]}(s) valued a {item[2]} each")
print() # add a line break in
def saveInventoryWhole(): # save the Dishes inventory as one object
try:
with open(objFileName, "wb") as fileOut:
pickle.dump(lstInventoryDishes, fileOut)
except Exception as e:
print("Error with file")
print(e)
def loadInventoryWhole(): # read the Dishes inventory in as one object
global lstInventoryDishes
try:
with open(objFileName, "rb") as fileIn:
lstInventoryDishes = pickle.load(fileIn)
except Exception as e:
print("Error with file")
print(e)
# Title: Exceptions and pickling module
# Dev: JNordbye
# Date: December/3/2018
# ChangeLog: (Who, When, What)
# J Nordbye 12/3/18, Added code to complete assignment 5
#
# -------------------------------------------------#
import pickle #import the pickle Module
#=------------------- Data -----------------------#
objFileName = "Inventory.dat"
objFileName2 = "Inventory2.dat"
lstInventoryDishes = [("Mug", 24.99, 5), ("Cup", 14.99, 10), ("Saucer", 9.99, 10)] # list of items in inventory
lstInventoryUtensils =[("Knife", 9.99, 25), ("Fork", 4.99, 20), ("Spoon", 4.99, 10)] # list of items in inventory
#------------------- Input/Output -------------------#
def listInventory( inInventory): # print out whats in the specifiedInventory
for item in inInventory:
print(f" {item[2]:2} {item[0]}(s) valued a {item[2]} each")
print() # add a line break in
def saveInventoryWhole(): # save the Dishes inventory as one object
try:
with open(objFileName, "wb") as fileOut:
pickle.dump(lstInventoryDishes, fileOut)
except Exception as e:
print("Error with file")
print(e)
def loadInventoryWhole(): # read the Dishes inventory in as one object
global lstInventoryDishes
try:
with open(objFileName, "rb") as fileIn:
lstInventoryDishes = pickle.load(fileIn)
except Exception as e:
print("Error with file")
print(e)
def saveInventoryIndivd(): # save each part of the Utensil inventory individually
try:
objFile = open(objFileName2, "wb")
for item in lstInventoryUtensils:
pickle.dump(item, objFile)
objFile.close()
except Exception as e:
print("Error with File")
print(e)
def loadInventoryIndivd(): # load each item from disk and add to the Utensil Inventory
try:
with open(objFileName2, "rb") as inFile:
while True:
try:
item = pickle.load(inFile)
lstInventoryUtensils.append(item)
except EOFError: # error check for reaching end of file.
break
except Exception as e:
print("Error with file")
print(e)
break
except Exception as e:
print("Error with file")
print(e)
#------------------- Processing ---------------------#
saveInventoryWhole() # save the Dishes inventory
lstInventoryDishes.clear() # clear out the list
loadInventoryWhole() # load the dishes inventory in from file
print("Dishes Inventory")
listInventory(lstInventoryDishes) # print out the Dishes list
saveInventoryIndivd() # save utensiles inventory to file
lstInventoryUtensils.clear() # clear the list
loadInventoryIndivd() # load the utensiles inventory in
print("Utensil Inventory")
listInventory(lstInventoryUtensils)
try:
objFile = open(objFileName2, "wb")
for item in lstInventoryUtensils:
pickle.dump(item, objFile)
objFile.close()
except Exception as e:
print("Error with File")
print(e)
def loadInventoryIndivd(): # load each item from disk and add to the Utensil Inventory
try:
with open(objFileName2, "rb") as inFile:
while True:
try:
item = pickle.load(inFile)
lstInventoryUtensils.append(item)
except EOFError: # error check for reaching end of file.
break
except Exception as e:
print("Error with file")
print(e)
break
except Exception as e:
print("Error with file")
print(e)
#------------------- Processing ---------------------#
saveInventoryWhole() # save the Dishes inventory
lstInventoryDishes.clear() # clear out the list
loadInventoryWhole() # load the dishes inventory in from file
print("Dishes Inventory")
listInventory(lstInventoryDishes) # print out the Dishes list
saveInventoryIndivd() # save utensiles inventory to file
lstInventoryUtensils.clear() # clear the list
loadInventoryIndivd() # load the utensiles inventory in
print("Utensil Inventory")
listInventory(lstInventoryUtensils)