This is a 100 Days challenge to learn a new language (Python). 100 Days of Code - The Complete Python Pro Bootcamp
I will post some notes to motivate myself to finish this challenge.
Exceptions
When exceptions occur, python program will stop and show some error messages.
There are some normal exceptions below.
FileNotFound
Ex:
with open("no_such_file.txt") as file:
print(file.read())
Result:
FileNotFoundError:
[Errno 2] No such file or directory: 'no_such_file.txt'
KeyError
Ex:
my_dict = {"key1": "value1", "key2": "value2"}
print(my_dict["no_such_key"])
Result:
KeyError: 'no_such_key'
IndexError
Ex:
my_list = [1, 2, 3]
print(my_list[4])
Result:
IndexError: list index out of range
TypeError
Ex:
my_str = "hello"
print(my_str + 123)
Result:
TypeError: can only concatenate str (not "int") to str
How to catch Exceptions
Using the following keywords:
try:
Something that might cause an exception.
except:
Do this if there was an exception.
else:
Do this if there were no exceptions.
finally:
Do this no matter what happens.
Ex:
try:
file = open("no_such_file.txt")
except:
print("except")
file = open("no_such_file.txt", "w")
file.write("new created file")
else:
print("else")
print(file.read())
finally:
print("finally")
file.close()
Result (first run):
except
finally
Result (second run):
else
new created file
finally
Our own exceptions?
We can utilize 'raise' statement and some built-in exception to create our own exceptions.
Take the following exp as an example, there is no syntax errors or exceptions if users enter their height larger than 300. But it does not make sense to be an input parameter as human's height.
Ex:
height = float(input("Your height in cm: "))
weight = float(input("Your weight in kg: "))
# Normal Human Being cannot be higher than 300cm
if height > 300:
raise ValueError("Height should not be larger than 300")
bmi = weight / (height / 100) ** 2
print(f"Your bmi is {weight / (height / 100) ** 2}")
Challenging - Revise NATO Alphabet Project
Catch exceptions if users enter non-alphabet characters.
Ex:
import pandas
# Using pandas to read csv file
nato_phonetic_alphabet_data_frame =
pandas.read_csv("nato_phonetic_alphabet.csv")
# Generate a dictionary to use alphabet as a key and relating word
as a value
# {"A": "Alfa", "B": "Bravo"}
nato_phonetic_alphabet_dict = {
row["letter"]: row["code"]
for (index, row) in nato_phonetic_alphabet_data_frame.iterrows()
}
""" Generate phonetic alphabet result based on the user input """
def generate_phonetic_alphabet_result():
# Ask users to enter a word
user_input = input("Enter a word? ")
try:
# Use List Comprehension to create a result list
# Loop through all letters of user input and get
the mapping word by dictionary
result = [nato_phonetic_alphabet_dict[letter] for letter in
user_input.upper()]
except KeyError:
# If users enter non-alphabet characters, then we cannot find it
from the nato_phonetic_alphabet_dict dictionary
# And program will throw KeyError Exception
print("Sorry, only letters in the alphabet please")
# In this case, we need to call the self function again
generate_phonetic_alphabet_result()
else:
print(result)
# Call this function to ask user input and then get relating results
generate_phonetic_alphabet_result()
JSON
JSON, JavaScript Object Notation.
Format: (look like python dictionary)
{
key: value,
key: value,
}
Ex (Write):
import json
# Write
with open("data.json", "w") as file:
json.dump({"key1": "value1"}, file, indent=4)
Result:
// data.json
{
"key1": "value1"
}
Ex (Read):
import json
# Load
with open("data.json", "r") as file:
print(json.load(file))
Result:
{'key1': 'value1'}
Ex (Update):
import json
# Update
# Read it frist
with open("data.json", "r") as file:
# Load JSON file first
data = json.load(file)
# Use update to add more data
data.update(
{
"key2": {
"inner_key1": "innver_value1",
"inner_key2": "innver_value2",
}
}
)
# Write it back
with open("data.json", "w") as file:
# Use dump function to write the updated data back to the file
json.dump(data, file, indent=4)
Result:
// data.json
{
"key1": "value1",
"key2": {
"inner_key1": "innver_value1",
"inner_key2": "innver_value2"
}
}
Challenging - Revise Password Manager
#1 Save file from txt to json.
#2 Catch Exceptions
#3 Add Search function
Ex:
import random
import tkinter as tk
from tkinter import messagebox
import pyperclip
import json
def find_password():
"""Find password from data.json"""
website = website_entry.get()
# Validation
if len(website) == 0:
messagebox.showerror(
title="Info",
message="Please make sure to enter website field"
)
return
try:
# Load data from data.json
with open("data.json", encoding="utf-8", mode="r") as file:
data = json.load(file)
except FileNotFoundError:
messagebox.showerror(title="Info", message="No Data File Found")
else:
# Continue from try clause
# If we can find website from data.json
if website in data:
websiteObj = data[website]
messagebox.showinfo(
title=website,
message=f"Email:{websiteObj['email']}\nPassword:
{websiteObj['pwd']}",
)
else:
messagebox.showerror(
title="Info",
message=f"No details for the {website} exists"
)
def copy_to_clipboard(message):
"""Use pyperclip library to copy message to clipboard"""
pyperclip.copy(message)
def generate_password():
"""Generate random password and show it to GUI"""
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",
]
numbers = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
symbols = ["!", "#", "$", "%", "&", "(", ")", "*", "+"]
password_letter_list = [
random.choice(letters) for _ in range(random.randint(8, 10))
]
password_symbols_list = [
random.choice(symbols) for _ in range(random.randint(2, 4))
]
password_numbers_list = [
random.choice(numbers) for _ in range(random.randint(2, 4))
]
password_list = password_letter_list + password_symbols_list +
password_numbers_list
random.shuffle(password_list)
password = "".join(password_list)
pwd_entry.insert(0, password)
copy_to_clipboard(password)
def save():
"""Save user info to the file system"""
website = website_entry.get()
username = username_entry.get()
pwd = pwd_entry.get()
# Form Validation
if len(website) == 0 or len(username) == 0 or len(pwd) == 0:
messagebox.showerror(
title="Info", message="Please make sure to enter all fields"
)
return
# Pop-up confirmation
is_ok = messagebox.askokcancel(
title=website,
message=f"Is that ok to save {username} / {pwd} ?",
)
if is_ok:
try:
# Open a file with r mode
# And load it
with open("data.json", encoding="utf-8", mode="r") as file:
data = json.load(file)
except FileNotFoundError:
# If there is a file not found exception
# Then, open a file with w mode
# And dump to json file directly since it will be the
# first record
with open("data.json", encoding="utf-8", mode="w") as file:
json.dump({website: {"email": username, "pwd": pwd}},
file, indent=4)
else:
# Continue from try clause
# Update python object data with the new record
data.update({website: {"email": username, "pwd": pwd}})
# Open a file with w mode
# And write updated python object back to json file
with open("data.json", encoding="utf-8", mode="w") as file:
json.dump(data, file, indent=4)
finally:
# Clear User Input
website_entry.delete(0, tk.END)
pwd_entry.delete(0, tk.END)
# Init
root = tk.Tk()
root.title("Password Manager")
root.config(padx=50, pady=50)
# Init canvas
canvas = tk.Canvas(width=200, height=200)
logo_image = tk.PhotoImage(file="logo.png")
canvas.create_image(100, 100, image=logo_image)
canvas.grid(column=1, row=0)
# Website
website_label = tk.Label(text="Website:")
website_label.grid(column=0, row=1)
website_entry = tk.Entry()
website_entry.grid(sticky="ew", padx=[0, 5], column=1, row=1)
# Focus entry
website_entry.focus()
# Search
search_btn = tk.Button(text="Search", command=find_password)
search_btn.grid(sticky="ew", padx=[5, 0], column=2, row=1)
# Email/Username
username_lable = tk.Label(text="Email/Username:")
username_lable.grid(column=0, row=2)
username_entry = tk.Entry()
username_entry.grid(sticky="ew", column=1, row=2, columnspan=2)
username_entry.insert(0, "frank@demo.com")
# Password
pwd_lable = tk.Label(text="Password:")
pwd_lable.grid(column=0, row=3)
pwd_entry = tk.Entry()
pwd_entry.grid(sticky="ew", padx=[0, 5], column=1, row=3)
# PWD Generation Btn
generate_pwd_btn = tk.Button(text="Generate Password",
command=generate_password)
generate_pwd_btn.grid(sticky="ew", padx=[5, 0], column=2, row=3)
# Add Btn
add_btn = tk.Button(text="Add", command=save)
add_btn.grid(sticky="ew", column=1, row=4, columnspan=2)
# Start the Event Loop
root.mainloop()
No comments:
Post a Comment