TIL Python Basics Day 30 - Errors, Exceptions and JSON Data
- 벨로그 사이트 오류로 티스토리 블로그로 이동
Errors, Exceptions and JSON Data: Improving the Password Vault GUI app
Catch exceptions
Why?: To continue executing the whole script, even though there are errors.
When there are errors in code, it simply terminates execution at the first error, before it reaches the end of the script; however, with exception handling, we can catch errors while executing the whole program without needing to terminate it in the middle.
try: Something that might cause an exception
In most cases, it will work most of the time, but it might not work
except: Do this if there was an exception
You want the computer to execute if there was an exception, if something went wrong and if was not the way that you expected it to go. then carry out this code
else: Do this if there were no exceptions
-if 'try' had not occured any errors
finally: Do this no matter what happens
It's always going to be executed anyways to tidy things up or clean things up
Type of Errors
FileNotFoundError
TypeError
IndexError
KeyError
Exception Handling
to prevent the program from crashing.
1.try
Try this, if fails, we will do except
try:
file = open("a_file.txt")
a_dictionary = {"key": "value"}
print(a_dictionary["key"])
2. except
if 'try:' didn't work, we will do this alternatively; however, if no error found at try level, nothing happens
Specifying Error:
if you give exception to catch a SPECIFIC situation, such as except FileNotFoundError, only catches an specified error (e.g.FileNotFoundError)
except FileNotFoundError:
file = open("a_file.txt", "w")
file.write("Something")
when catching an exception, we can hold an error message as a variable, and print out the message
except KeyError as error_message:
print(f"The key {error_message} does not exist.")
3. else
else always has to come after except. except cannot be skipped before else.
try:
texting code
exccept:
if there is an exception(error), execute this code
else:
if there is NO excption(error), execute this code
4.finally
regardless error occurance, finally can skip 'except' and 'else'
#Exception Handling
try:
file = open("a_file.txt")
a_dictionary = {"key": "value"}
print(a_dictionary["key"])
except FileNotFoundError:
file = open("a_file.txt", "w")
file.write("Something")
else:
content = file.read()
print(content)
finally:
raise TypeError("This is an error that I made up.")
Raise your own exceptions
Even though the code is perfectly valid, in fact, it's going to generate wrong results. In the example code, human height cannot be over 3meters, so logically wrong; hence, raise an error
#BMI Example
height = float(input("Height: "))
weight = int(input("Weight: "))
if height > 3:
raise ValueError("Human Height should not be over 3 meters.")
bmi = weight / height ** 2
print(bmi)
Task.1
Use what you've learnt about exception handling to prevent the program from crashing. If the user enters something that is out of range just print a default output of "Fruit pie". e.g.
def make_pie(index):
fruits = ["Apple", "Pear", "Orange"]
#TODO: Catch the exception and make sure the code runs without crashing.
def make_pie(index):
try:
fruit = fruits[index]
except IndexError:
print("Fruit Pie")
else:
print(fruit + " pie")
make_pie(4)
#printed: Fruit Pie
*Task.2 *
facebook_posts = [
{'Likes': 21, 'Comments': 2},
{'Likes': 13, 'Comments': 2, 'Shares': 1},
{'Likes': 33, 'Comments': 8, 'Shares': 3},
{'Comments': 4, 'Shares': 2},
{'Comments': 1, 'Shares': 1},
{'Likes': 19, 'Comments': 3}
]
total_likes = 0
for post in facebook_posts:
try:
total_likes = total_likes + post['Likes']
except KeyError:
total_likes += 0
#or
pass
print(total_likes)
#printed: 86
Task.3 Improving NATO
phonetic_dict = {'A': 'Alfa', 'B': 'Bravo', 'C': 'Charlie', 'D': 'Delta', 'E': 'Echo', 'F': 'Foxtrot', 'G': 'Golf', 'H': 'Hotel', 'I': 'India', 'J': 'Juliet', 'K': 'Kilo', 'L': 'Lima', 'M': 'Mike', 'N': 'November', 'O': 'Oscar', 'P': 'Papa', 'Q': 'Quebec', 'R': 'Romeo', 'S': 'Sierra', 'T': 'Tango', 'U': 'Uniform', 'V': 'Victor', 'W': 'Whiskey', 'X': 'X-ray', 'Y': 'Yankee', 'Z': 'Zulu'}
def generate_phonetic():
word = input("Enter a word: ").upper()
try:
output_list = [phonetic_dict[letter] for letter in word]
except KeyError:
print("Sorry, only letters in the alphabet please")
generate_phonetic()
else:
print(output_list)
generate_phonetic()
#printed:
Enter a word: 234
Sorry, only letters in the alphabet please
Enter a word: hi
['Hotel', 'India']
Json
Json is JavaScript Object Notation
-Dictionary format
-popular way to transfering data across the internet
Write
json.dump()
-Data format should be nested dictionary {key:{key:value}}
new_data = {
website: {
"email": email,
"password": password,
}
}
-Open a .json file, store dict values into data_file(==data.json), indent=4 is to create spaces on json file
with open("data.json", "w") as data_file:
json.dump(new_data, data_file, indent=4)
#input values stored in the data.json file. Indented 4 times
{
"e": {
"email": "angela@gmail.com",
"password": "t!zYK2+zFX*6ZF"
}
}
Read
-Take json data and convert it into python dictionaryjson.load()
with open("data.json", "r") as data_file:
data = json.load(data_file)
print(data)
#printed: console
{'e': {'email': 'angela@gmail.com', 'password': 't!zYK2+zFX*6ZF'}}
Update
-Update only works when there is an existing data in the file.
if we use append as with open("data.json", "a")
, it doesn't make a valid data structure in the file and cause an error.
example of invalid json data. It created two dictionaries in one file.
{
"a": {
"email": "angela@gmail.com",
"password": "qjc!dU$7WTmk1(V"
}
}
{
"b": {
"email": "angela@gmail.com",
"password": "2t&+kNRlcc6Mj"
}
}
json.update()
with open("data.json", "r") as data_file:
#Reading old data
data = json.load(data_file)
#Updating old data with new data/ variable data is json
data.update(new_data)
with open("data.json", "w") as data_file:
#Saving updated data
json.dump(data, data_file, indent=4)
- Nicely formatted at json.file
{
"a": {
"email": "angela@gmail.com",
"password": "qjc!dU$7WTmk1(V"
},
"b": {
"email": "angela@gmail.com",
"password": "2t&+kNRlcc6Mj"
},
}
- Applied exception handling to password project
else: try: with open("data.json", "r") as data_file: # Reading old data data = json.load(data_file)
except FileNotFoundError :
with open("data.json", "w") as data_file:
json.dump(new_data, data_file, indent=4)
else:
# Updating old data with new data/ variable data is json
data.update(new_data)
with open("data.json", "w") as data_file:
# Saving updated data
json.dump(data, data_file, indent=4)
finally:
website_entry.delete(0, END)
password_entry.delete(0, END)
### Final Proejct.
#### Password Manager with search function (with Json file)
 
Final code
from tkinter import *
from tkinter import messagebox
from random import choice, randint, shuffle
import pyperclip
import json
---------------------------- PASSWORD SEARCH -------------------------------
def find_password():
website = website_entry.get()
try:
with open("data.json", "r") as data_file:
# Reading old data
data = json.load(data_file) # dictionary
except FileNotFoundError:
messagebox.showwarning(title="info",
message="No Data File Found")
else:
if website in data:
password = data[website]['password']
messagebox.askokcancel(title="info",
message=f"These are the details for {website}: \nPassword: {password}\n ")
elif website not in data:
messagebox.showwarning(title="info",
message="No details for the website exists.")
---------------------------- PASSWORD GENERATOR -------------------------------
#Password Generator Project
def generate_password():
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
symbols = ['!', '#', '$', '%', '&', '(', ')', '*', '+']
password_letters = [choice(letters) for _ in range(randint(8, 10))]
password_symbols = [choice(symbols) for _ in range(randint(2, 4))]
password_numbers = [choice(numbers) for _ in range(randint(2, 4))]
password_list = password_letters + password_symbols + password_numbers
shuffle(password_list)
password = "".join(password_list)
password_entry.insert(0, password)
pyperclip.copy(password)
---------------------------- SAVE PASSWORD -------------------------------
def save():
website = website_entry.get()
email = email_entry.get()
password = password_entry.get()
new_data = {
website: {
"email": email,
"password": password,
}
}
if len(website) == 0 or len(password) == 0:
messagebox.showinfo(title="Oops", message="Please make sure you haven't left any fields empty.")
else:
try:
with open("data.json", "r") as data_file:
# Reading old data
data = json.load(data_file)
except FileNotFoundError :
with open("data.json", "w") as data_file:
json.dump(new_data, data_file, indent=4)
else:
# Updating old data with new data/ variable data is json
data.update(new_data)
with open("data.json", "w") as data_file:
# Saving updated data
json.dump(data, data_file, indent=4)
finally:
website_entry.delete(0, END)
password_entry.delete(0, END)
---------------------------- UI SETUP -------------------------------
window = Tk()
window.title("Password Manager")
window.config(padx=50, pady=50)
canvas = Canvas(height=200, width=200)
logo_img = PhotoImage(file="logo.png")
canvas.create_image(100, 100, image=logo_img)
canvas.grid(row=0, column=1)
#Labels
website_label = Label(text="Website:")
website_label.grid(row=1, column=0)
email_label = Label(text="Email/Username:")
email_label.grid(row=2, column=0)
password_label = Label(text="Password:")
password_label.grid(row=3, column=0)
#Entries
website_entry = Entry(width=41)
website_entry.grid(row=1, column=1, columnspan=2)
website_entry.focus()
email_entry = Entry(width=41)
email_entry.grid(row=2, column=1, columnspan=2)
email_entry.insert(0, "angela@gmail.com")
password_entry = Entry(width=25)
password_entry.grid(row=3, column=1)
Buttons
search_button = Button(text="Search", width=15, command=find_password)
search_button.grid(row=1, column=2)
generate_password_button = Button(text="Generate Password", command=generate_password)
generate_password_button.grid(row=3, column=2)
add_button = Button(text="Add", width=42, command=save)
add_button.grid(row=4, column=1, columnspan=2)
window.mainloop()
```
Murphy's law is an adage or epigram that is typically stated as: "Anything that can go wrong will go wrong".
- The Starbucks Edict - As soon as you sit down to a cup of hot coffee, your boss will ask you to do something which will last until the coffee is cold. Murphy's Law of Lockers -If there are only two people in a locker room, they will have adjacent lockers
- Yhprum's law is the opposite of Murphy's law. The simple formula of Yhprum's law is: "Everything that can work, will work.