Error Handling: допомагаємо programs вижити

Повертаємось до Python.
У попередній лекції ти вивчив files.
Твої programs навчилися save data і read it later.
Ти писав щось таке:
with open("tasks.txt", "r") as file:
content = file.read()
Дуже добре.
Тепер твої programs можуть remember things.
Tasks.
Notes.
Contacts.
Small pieces of digital memory.
Beautiful.
Але тепер маємо іншу проблему.
Programs crash.
Багато.
Іноді тому, що file missing.
Іноді тому, що user enters text instead of a number.
Іноді тому, що ти divide by zero.
Іноді тому, що code мав tiny mistake, який ховався як ninja за bracket.
Приклад:
age = int(input("Age: "))
Якщо user напише:
banana
Python скаже:
ValueError
І program crashes.
Дуже dramatic.
Дуже Python.
Дуже normal.
Error handling допомагає твоїй program survive problems.
Замість crash, program може respond calmly.
Наприклад:
Please enter a valid number.
Набагато краще.
Набагато more professional.
Набагато менше “program exploded because someone typed banana”.
Що ти вивчиш
У цій лекції ти вивчиш:
- що таке errors;
- чому programs crash;
- що таке exceptions;
- як використовувати
try; - як використовувати
except; - як handle
ValueError; - як handle
FileNotFoundError; - як handle
ZeroDivisionError; - як ask for input again after an error;
- як не ловити занадто багато errors;
- як combine error handling with files;
- як build safer beginner programs;
- типові beginner mistakes з error handling.
До кінця цієї лекції твої programs будуть more stable.
Вони не будуть panic immediately.
Вони будуть handle common problems.
Вони survive users.
А users небезпечні.
Especially when the user is you at midnight.
Що таке error?
Error — це problem, який зупиняє program від correct work.
Приклад:
number = int("banana")
Python не може convert "banana" to a number.
Тому він дає error:
ValueError
Інший приклад:
result = 10 / 0
Python дає:
ZeroDivisionError
Бо division by zero is not allowed.
Інший приклад:
with open("missing.txt", "r") as file:
content = file.read()
Python дає:
FileNotFoundError
Бо file does not exist.
Errors нормальні.
Це не proof, що ти поганий у programming.
Це proof, що programming is programming.
Welcome.
Що таке exception?
У Python багато runtime errors називаються exceptions.
Exception happens, коли Python runs into a problem while the program is running.
Examples:
ValueError
FileNotFoundError
ZeroDivisionError
NameError
TypeError
IndexError
KeyError
Ти вже бачив деякі з них.
Можливо, too many.
Це нормально.
Exception зазвичай stops the program.
Unless you handle it.
Error handling означає:
If something goes wrong, do something safe instead of crashing.
Для цього потрібні try і except.
Дуже useful.
Дуже important.
Дуже “please do not explode”.
Твій перший try і except
Створи файл:
error_handling.py
Напиши:
try:
number = int(input("Enter a number: "))
print(f"You entered: {number}")
except ValueError:
print("That was not a valid number.")
Запусти.
Якщо введеш:
25
Output:
You entered: 25
Якщо введеш:
banana
Output:
That was not a valid number.
Program не crashes.
Excellent.
Python tried to run risky code.
Коли failed, Python jumped to except.
Дуже civilized.
Дуже useful.
Much better than screaming in red text.
Як працюють try і except
Basic structure:
try:
risky_code
except SomeError:
code_to_run_if_error_happens
Приклад:
try:
age = int(input("Age: "))
print(age)
except ValueError:
print("Please enter a number.")
try block містить code that might fail.
except block містить code, який runs if selected error happens.
Думай про це так:
Try this.
If this specific problem happens, do this instead.
Це як safety net.
Without safety net, program falls.
With safety net, program says:
Nice try, banana input.
And continues.
Handling ValueError
ValueError часто happens when converting input.
Приклад:
age = int(input("Age: "))
Якщо user enters:
hello
Python cannot convert it to an integer.
So it raises:
ValueError
Safer version:
try:
age = int(input("Age: "))
print(f"You are {age} years old.")
except ValueError:
print("Age must be a number.")
Це very common.
User input dangerous.
Users type strange things.
Sometimes by mistake.
Sometimes because they are testing your program.
Sometimes because they are chaos with fingers.
Тому always be careful with user input.
Ask again after an error
Замість того, щоб print error і stop, можна ask again.
Приклад:
while True:
try:
age = int(input("Age: "))
break
except ValueError:
print("Please enter a valid number.")
print(f"You are {age} years old.")
Як це works:
Start an infinite loop.
Ask for age.
Try to convert it.
If it works, break the loop.
If it fails, show a message and ask again.
Приклад:
Age: banana
Please enter a valid number.
Age: hello
Please enter a valid number.
Age: 25
You are 25 years old.
Це much better.
Program does not die.
Вона educates the user.
Gently.
Like a patient teacher.
But inside, it is probably tired.
Helper function для safe integer input
Можемо покласти цю logic у function.
Створи файл:
safe_input.py
Напиши:
def get_integer(prompt):
while True:
try:
number = int(input(prompt))
return number
except ValueError:
print("Please enter a valid number.")
age = get_integer("Age: ")
print(f"You are {age} years old.")
Тепер get_integer() keeps asking until user enters valid integer.
Це very useful.
Можеш reuse it many times.
Приклад:
quantity = get_integer("Quantity: ")
year = get_integer("Year: ")
score = get_integer("Score: ")
Functions plus error handling.
Дуже добре.
Дуже clean.
Дуже “we are becoming serious now”.
Handling float input
Іноді потрібні decimal numbers.
Приклад:
price = float(input("Price: "))
Це також може raise ValueError.
Safer function:
def get_float(prompt):
while True:
try:
number = float(input(prompt))
return number
except ValueError:
print("Please enter a valid number.")
price = get_float("Price: ")
print(f"Price: {price:.2f}")
Якщо user enters:
abc
Program asks again.
Якщо user enters:
19.99
It works.
Це useful для:
prices
measurements
averages
discounts
percentages
Basically, anything where decimals enter the room wearing serious shoes.
Handling ZeroDivisionError
Division by zero is not allowed.
Приклад:
result = 10 / 0
Python дає:
ZeroDivisionError
Safer example:
try:
number = float(input("Number: "))
result = 100 / number
print(f"Result: {result}")
except ZeroDivisionError:
print("You cannot divide by zero.")
except ValueError:
print("Please enter a valid number.")
Якщо user enters:
0
Output:
You cannot divide by zero.
Якщо user enters:
banana
Output:
Please enter a valid number.
Це handles two possible problems.
Дуже practical.
Дуже useful.
Дуже “the program has seen things”.
Multiple except blocks
Можна handle different errors separately.
Приклад:
try:
number = int(input("Enter a number: "))
result = 100 / number
print(result)
except ValueError:
print("That was not a valid number.")
except ZeroDivisionError:
print("You cannot divide by zero.")
Це good, бо different errors need different messages.
ValueError означає:
The input was not a number.
ZeroDivisionError означає:
The number was zero.
Different problem.
Different response.
Good programs explain problems clearly.
Bad programs say:
Something went wrong.
And then disappear into the fog.
Do not be fog.
Handling FileNotFoundError
Ти вже бачив files.
Reading a missing file causes FileNotFoundError.
Приклад:
try:
with open("notes.txt", "r") as file:
content = file.read()
print(content)
except FileNotFoundError:
print("The file does not exist yet.")
Якщо notes.txt exists, program reads it.
Якщо it does not exist, program prints:
The file does not exist yet.
Це much better than crashing.
File errors common.
Especially when:
the file was never created
the file name is wrong
the file is in another folder
you are running Python from the wrong directory
Classic file drama.
Very normal.
Very fixable.
Loading tasks safely
У попередній лекції ми saved tasks in a file.
Тепер можемо load them safely.
Приклад:
def load_tasks():
tasks = []
try:
with open("tasks.txt", "r") as file:
for line in file:
tasks.append(line.strip())
except FileNotFoundError:
pass
return tasks
If file exists, tasks are loaded.
If file does not exist, function returns empty list.
Це good.
The first time your program runs, there may be no file yet.
That is not a disaster.
It is just a new program with no data.
Very innocent.
Very empty.
Very ready to become messy later.
Using else with try
Python також supports else with try.
else block runs only if no error happens.
Приклад:
try:
number = int(input("Enter a number: "))
except ValueError:
print("Invalid number.")
else:
print(f"Good number: {number}")
If input valid:
Enter a number: 10
Good number: 10
If input invalid:
Enter a number: banana
Invalid number.
else block optional.
You do not always need it.
Але sometimes it makes code clearer.
Simple idea:
try risky thing
except if it fails
else if it succeeds
Very tidy.
Very Python.
Like a small legal contract for errors.
Using finally
Python also has finally.
finally block runs no matter what.
Приклад:
try:
number = int(input("Enter a number: "))
print(number)
except ValueError:
print("Invalid number.")
finally:
print("Program finished.")
If user enters a number, finally runs.
If user enters bad input, finally still runs.
Example:
Enter a number: banana
Invalid number.
Program finished.
finally useful, коли треба clean up something.
For beginner programs, you will not need it often.
Але good to know it exists.
Як fire extinguisher.
You may not use it every day.
But you want it there.
Не ловити everything too early
Можеш побачити code like this:
try:
number = int(input("Number: "))
except:
print("Something went wrong.")
Це catches every error.
It works.
But usually not ideal.
Why?
Бо it can hide real bugs.
Better:
try:
number = int(input("Number: "))
except ValueError:
print("Please enter a valid number.")
Це handles the specific problem you expect.
Specific error handling better.
It tells you what really happened.
Catching everything is like putting a blanket over the problem.
Problem still there.
Now it is just warmer.
And harder to see.
Не став too much code у try
Bad:
try:
name = input("Name: ")
age = int(input("Age: "))
city = input("City: ")
print(user_name)
except ValueError:
print("Invalid age.")
Це risky, бо try block contains too much.
There may be other errors inside.
Наприклад:
print(user_name)
could cause NameError.
Better:
name = input("Name: ")
try:
age = int(input("Age: "))
except ValueError:
print("Invalid age.")
city = input("City: ")
Keep try focused on the code that may produce expected error.
This makes debugging easier.
And easier debugging is happiness.
Small happiness.
But still happiness.
Error handling не для hiding bad code
Important lesson.
Error handling is not a trash bin for broken logic.
Bad idea:
try:
broken_code_here
except:
pass
This hides problems.
Program may continue, but something is wrong.
And now you do not know what.
except: pass can be useful in rare cases.
But beginners should avoid using it casually.
If you ignore every error, your program becomes a mysterious creature.
It runs.
Maybe.
It does things.
Maybe.
Nobody knows why.
This is not engineering.
This is haunted programming.
Avoid.
Міні-програма: safe age input
Створи файл:
safe_age.py
Напиши:
while True:
try:
age = int(input("Age: "))
break
except ValueError:
print("Please enter a valid age.")
print(f"Your age is {age}.")
Приклад:
Age: hello
Please enter a valid age.
Age: 33
Your age is 33.
Ця program keeps asking until user enters valid integer.
Simple.
Useful.
Much better than crashing.
Це very common beginner pattern.
Use it often.
Your users will type strange things.
Your program should not faint.
Міні-програма: safe calculator
Створи файл:
safe_calculator.py
Напиши:
try:
first_number = float(input("First number: "))
second_number = float(input("Second number: "))
result = first_number / second_number
print(f"Result: {result:.2f}")
except ValueError:
print("Please enter valid numbers.")
except ZeroDivisionError:
print("You cannot divide by zero.")
Приклад:
First number: 10
Second number: 2
Result: 5.00
Якщо user enters:
Second number: 0
Output:
You cannot divide by zero.
Ця program handles two common problems.
Invalid input.
Division by zero.
Дуже useful.
Дуже practical.
Дуже “calculator has survival instincts now”.
Міні-програма: safe notes reader
Створи файл:
safe_notes_reader.py
Напиши:
try:
with open("notes.txt", "r") as file:
print("Notes:")
for line in file:
print(f"- {line.strip()}")
except FileNotFoundError:
print("No notes found yet.")
If file exists, it shows notes.
If not, it prints:
No notes found yet.
Це clean.
Missing file is not always a disaster.
Sometimes it just means:
No data yet.
That is a normal situation.
Good programs understand normal situations.
Bad programs panic and throw red text.
We prefer calm programs.
Very Zen.
Very Python.
Міні-програма: safer task manager
Тепер improve task manager.
Створи файл:
safe_task_manager.py
Напиши:
FILE_NAME = "tasks.txt"
def load_tasks():
tasks = []
try:
with open(FILE_NAME, "r") as file:
for line in file:
tasks.append(line.strip())
except FileNotFoundError:
pass
return tasks
def save_tasks(tasks):
with open(FILE_NAME, "w") as file:
for task in tasks:
file.write(task + "\n")
def show_menu():
print("----- Task Manager -----")
print("1. Add task")
print("2. Show tasks")
print("3. Remove task")
print("q. Quit")
def add_task(tasks):
task = input("Task: ")
tasks.append(task)
save_tasks(tasks)
print("Task saved.")
def show_tasks(tasks):
if len(tasks) == 0:
print("No tasks yet.")
else:
print("Tasks:")
for index, task in enumerate(tasks, start=1):
print(f"{index}. {task}")
def remove_task(tasks):
if len(tasks) == 0:
print("No tasks to remove.")
return
show_tasks(tasks)
try:
task_number = int(input("Task number to remove: "))
index = task_number - 1
if index < 0 or index >= len(tasks):
print("Invalid task number.")
return
removed_task = tasks.pop(index)
save_tasks(tasks)
print(f"Removed: {removed_task}")
except ValueError:
print("Please enter a valid number.")
tasks = load_tasks()
while True:
show_menu()
choice = input("Choose an option: ").lower()
if choice == "1":
add_task(tasks)
elif choice == "2":
show_tasks(tasks)
elif choice == "3":
remove_task(tasks)
elif choice == "q":
print("Goodbye.")
break
else:
print("Unknown option.")
Це stronger program.
It uses:
- files;
- functions;
- lists;
- loops;
try;except;ValueError;FileNotFoundError;enumerate();- safe task removal.
Це real beginner software.
Small, yes.
But real.
It saves data.
Loads data.
Handles missing files.
Handles bad input.
This is how programs grow.
One safety net at a time.
Що робить enumerate()
У task manager ми used:
for index, task in enumerate(tasks, start=1):
print(f"{index}. {task}")
enumerate() gives both:
number
item
Приклад:
tasks = ["Buy milk", "Study Python"]
for index, task in enumerate(tasks, start=1):
print(f"{index}. {task}")
Output:
1. Buy milk
2. Study Python
Це useful, коли showing numbered lists.
User sees task number 1.
Python list index is actually 0.
Тому when removing a task, we do:
index = task_number - 1
User-friendly number.
Python-friendly index.
Diplomacy.
Between humans and machines.
Very important.
Типова помилка: handling wrong error
Приклад:
try:
age = int(input("Age: "))
except FileNotFoundError:
print("File not found.")
This does not make sense.
Risky code is converting input to int.
Likely error is:
ValueError
Correct:
try:
age = int(input("Age: "))
except ValueError:
print("Invalid age.")
Handle the error that can actually happen.
Otherwise your program is guarding the wrong door.
And the bug comes through the window.
Classic bug behavior.
Типова помилка: too broad except
Not ideal:
try:
age = int(input("Age: "))
except:
print("Something went wrong.")
Better:
try:
age = int(input("Age: "))
except ValueError:
print("Please enter a valid age.")
Specific is better.
The more specific your error handling is, the easier debugging becomes.
Vague error message helps nobody.
Especially you.
And you are the one who must fix the code.
Be kind to future you.
Future you has already suffered enough.
Типова помилка: ignoring the error completely
Dangerous:
try:
age = int(input("Age: "))
except ValueError:
pass
If user enters invalid input, nothing happens.
Program silently ignores the problem.
This can create confusing bugs.
Better:
try:
age = int(input("Age: "))
except ValueError:
print("Please enter a valid age.")
At least tell the user what happened.
Silent failure is dangerous.
It is like a smoke alarm that whispers.
Not useful.
Типова помилка: using variable that was not created
Приклад:
try:
age = int(input("Age: "))
except ValueError:
print("Invalid age.")
print(age)
If user enters invalid input, age is never created.
Then:
print(age)
can cause:
NameError
Better:
try:
age = int(input("Age: "))
print(age)
except ValueError:
print("Invalid age.")
Or use a loop until valid input is received.
Дуже important.
If variable is created inside try block, make sure it exists before using it later.
Python is not magic.
It will not invent the variable out of pity.
Типова помилка: error handling without fixing flow
Bad:
try:
number = int(input("Number: "))
except ValueError:
print("Invalid number.")
result = number * 2
print(result)
If input invalid, number may not exist.
Better:
while True:
try:
number = int(input("Number: "))
break
except ValueError:
print("Invalid number.")
result = number * 2
print(result)
Now program only continues when number is valid.
That is good flow.
Error handling is not just about printing messages.
It is about controlling what happens next.
Very important.
Very program architecture.
Small architecture.
But still architecture.
Практика
Створи файл:
practice_error_handling.py
Напиши program, яка:
- asks the user for a price;
- asks the user for a quantity;
- calculates the total;
- handles invalid input;
- keeps asking until input is valid.
Приклад рішення:
def get_float(prompt):
while True:
try:
value = float(input(prompt))
return value
except ValueError:
print("Please enter a valid number.")
def get_integer(prompt):
while True:
try:
value = int(input(prompt))
return value
except ValueError:
print("Please enter a valid whole number.")
price = get_float("Price: ")
quantity = get_integer("Quantity: ")
total = price * quantity
print(f"Total: {total:.2f}")
Приклад:
Price: hello
Please enter a valid number.
Price: 10.50
Quantity: banana
Please enter a valid whole number.
Quantity: 3
Total: 31.50
Це clean program.
It handles bad input.
It reuses functions.
It calculates safely.
Very good practice.
Very shop-like.
Taxes are still hiding nearby.
But not today.
Міні-завдання
Створи файл:
safe_contact_book.py
Побудуй small contact book, яка:
- saves contacts to
contacts.txt; - loads contacts from the file;
- lets the user add contacts;
- lets the user show contacts;
- handles missing file safely;
- handles wrong menu options;
- does not crash on first run.
Simple contact format:
name,email,phone
Example structure:
FILE_NAME = "contacts.txt"
def load_contacts():
contacts = []
try:
with open(FILE_NAME, "r") as file:
for line in file:
parts = line.strip().split(",")
if len(parts) == 3:
contact = {
"name": parts[0],
"email": parts[1],
"phone": parts[2]
}
contacts.append(contact)
except FileNotFoundError:
pass
return contacts
def save_contacts(contacts):
with open(FILE_NAME, "w") as file:
for contact in contacts:
file.write(f"{contact['name']},{contact['email']},{contact['phone']}\n")
def add_contact(contacts):
contact = {
"name": input("Name: "),
"email": input("Email: "),
"phone": input("Phone: ")
}
contacts.append(contact)
save_contacts(contacts)
print("Contact saved.")
def show_contacts(contacts):
if len(contacts) == 0:
print("No contacts yet.")
else:
print("Contacts:")
for contact in contacts:
print("-----")
print(f"Name: {contact['name']}")
print(f"Email: {contact['email']}")
print(f"Phone: {contact['phone']}")
def show_menu():
print("----- Contact Book -----")
print("1. Add contact")
print("2. Show contacts")
print("q. Quit")
contacts = load_contacts()
while True:
show_menu()
choice = input("Choose an option: ").lower()
if choice == "1":
add_contact(contacts)
elif choice == "2":
show_contacts(contacts)
elif choice == "q":
print("Goodbye.")
break
else:
print("Unknown option.")
Ця program combines many things you learned:
- variables;
- strings;
- lists;
- dictionaries;
- loops;
- conditions;
- functions;
- files;
- basic error handling.
That is a lot.
Це вже не просто “Hello, World!”.
Це small real program.
It saves data.
Loads data.
Uses structured information.
Handles missing files.
Very strong progress.
Very Python.
Checklist для початківців
Коли твій error handling не працює, перевір:
Did I put risky code inside try?
Am I catching the correct error?
Did I use ValueError for invalid number conversion?
Did I use FileNotFoundError for missing files?
Did I use ZeroDivisionError for division by zero?
Did I accidentally catch everything with bare except?
Am I hiding errors with pass?
Does the program continue safely after an error?
Could a variable be missing after a failed try block?
Should I use a loop to ask again?
Is my try block too large?
Error handling is not about making errors disappear.
It is about responding correctly.
Good program does not pretend problems do not exist.
Good program says:
I expected this problem.
Here is what we do.
Very calm.
Very adult.
Very useful.
Підсумок
Сьогодні ти вивчив:
- errors are normal in programming;
- exceptions happen when Python runs into runtime problems;
trycontains risky code;excepthandles selected errors;ValueErroroften happens with invalid number conversion;FileNotFoundErrorhappens when reading missing files;ZeroDivisionErrorhappens when dividing by zero;- loops can ask for input again after an error;
- helper functions can make safe input reusable;
- multiple
exceptblocks can handle different errors; elseruns when no error happens;finallyruns no matter what;- catching every error can hide bugs;
tryblocks should usually stay focused;- error handling should improve program flow, not hide broken logic.
Це великий крок.
Твої programs now safer.
Вони можуть handle bad input.
Вони можуть handle missing files.
Вони можуть avoid dramatic crashes.
Вони можуть guide the user instead of exploding.
Це те, що real programs need.
Бо real life messy.
Files go missing.
Users type bananas.
Numbers become zero.
І sometimes you forget what you wrote yesterday.
Error handling helps your program survive the mess.
Дуже useful.
Дуже Python.
Дуже real.
Наступна лекція
У наступній лекції ми вивчимо modules та imports.
Ти навчишся split code into different files і reuse code across your project.
Замість того, щоб тримати everything in one giant file, ти organize code like this:
main.py
helpers.py
calculator.py
tasks.py
Потім ти будеш import functions from one file into another.
Це ще один huge step toward real projects.
Бо real projects are not one giant file.
Usually.
Unless someone suffered.
And we do not want that.
We want clean structure.
Reusable code.
And fewer files named final_final_really_final.py.
Very Python.
Very next level.