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.