Python · Синтаксис · Начальный уровень
Основы обработки ошибок
Научитесь обрабатывать ошибки с помощью try/except/else/finally, генерировать собственные исключения и писать надёжный Python-код.
Краткое введение в тему и пояснения перед упражнениями (упражнения ниже):
Паттерны обработки ошибок
#Справочник: обработка ошибок
#Упражнения:
Безопасное преобразование в int
#def safe_int(s, default=0):
pass
print(safe_int("42")) # 42
print(safe_int("abc")) # 0
print(safe_int("abc", -1)) # -1
Решение
def safe_int(s, default=0):
try:
return int(s)
except (ValueError, TypeError):
return default
print(safe_int("42")) # 42
print(safe_int("abc")) # 0
print(safe_int("abc", -1)) # -1
Безопасное деление
#def safe_divide(a, b):
pass
print(safe_divide(10, 2)) # 5.0
print(safe_divide(10, 0)) # None
Решение
def safe_divide(a, b):
try:
return a / b
except ZeroDivisionError:
return None
print(safe_divide(10, 2)) # 5.0
print(safe_divide(10, 0)) # None
Несколько типов исключений
#def parse_value(s):
pass
print(parse_value("42")) # 42 (int)
print(parse_value("3.14")) # 3.14 (float)
print(parse_value("abc")) # None
Решение
def parse_value(s):
try:
return int(s)
except ValueError:
pass
try:
return float(s)
except ValueError:
return None
print(parse_value("42")) # 42
print(parse_value("3.14")) # 3.14
print(parse_value("abc")) # None
Валидация возраста
#def validate_age(age):
pass
print(validate_age(25)) # 25
try:
validate_age("old")
except TypeError as e:
print(e)
try:
validate_age(200)
except ValueError as e:
print(e)
Решение
def validate_age(age):
if not isinstance(age, int):
raise TypeError(f"Expected int, got {type(age).__name__}")
if not 0 <= age <= 150:
raise ValueError("Age must be between 0 and 150")
return age
print(validate_age(25)) # 25
try:
validate_age("old")
except TypeError as e:
print(e)
try:
validate_age(200)
except ValueError as e:
print(e)
Использование else
#def read_number(s):
pass
print(read_number("3.14")) # выводит "Got: 3.14", возвращает 3.14
print(read_number("abc")) # выводит "Invalid input", возвращает None
Решение
def read_number(s):
try:
value = float(s)
except ValueError:
print("Invalid input")
return None
else:
print(f"Got: {value:.2f}")
return value
print(read_number("3.14")) # Got: 3.14
print(read_number("abc")) # Invalid input
Очистка в finally
#def safe_open(path):
pass
print(safe_open("/tmp/test_eh.txt")) # содержимое или ""
print(safe_open("/tmp/no_such_file.txt")) # ""
Решение
def safe_open(path):
f = None
try:
f = open(path, encoding="utf-8")
return f.read()
except FileNotFoundError:
return ""
finally:
print("Closing file")
if f:
f.close()
import pathlib
pathlib.Path("/tmp/test_eh.txt").write_text("hello", encoding="utf-8")
print(safe_open("/tmp/test_eh.txt"))
print(safe_open("/tmp/no_such_file.txt"))
Безопасный доступ к вложенному словарю
#def get_user_city(data, username):
pass
users = {"alice": {"address": {"city": "Kyiv"}}}
print(get_user_city(users, "alice")) # Kyiv
print(get_user_city(users, "bob")) # Unknown
Решение
def get_user_city(data, username):
try:
return data[username]["address"]["city"]
except KeyError:
return "Unknown"
users = {"alice": {"address": {"city": "Kyiv"}}}
print(get_user_city(users, "alice")) # Kyiv
print(get_user_city(users, "bob")) # Unknown
Raise с валидацией
#def create_username(name):
pass
print(create_username("Alice")) # alice
print(create_username(" Bob ")) # bob
try:
create_username("")
except ValueError as e:
print(e)
Решение
def create_username(name):
name = name.strip()
if not name:
raise ValueError("Username cannot be empty")
if len(name) > 20:
raise ValueError("Username must be 20 characters or less")
if " " in name:
raise ValueError("Username cannot contain spaces")
return name.lower()
print(create_username("Alice")) # alice
print(create_username(" Bob ")) # bob
try:
create_username("")
except ValueError as e:
print(e)
Цепочка операций
#def process(text):
pass
print(process("42,extra")) # 42
print(process("no-comma")) # None
print(process(None)) # None
Решение
def process(text):
try:
upper = text.upper()
first = upper.split(",")[0]
return int(first)
except (ValueError, IndexError, AttributeError):
return None
print(process("42,extra")) # 42
print(process("no-comma")) # None
print(process(None)) # None
Отчёт об исключениях
#def run_all(functions, input_value):
pass
funcs = [str, int, lambda x: x / 0]
print(run_all(funcs, "42"))
# ["42", 42, "ERROR: division by zero"]
Решение
def run_all(functions, input_value):
results = []
for fn in functions:
try:
results.append(fn(input_value))
except Exception as e:
results.append(f"ERROR: {e}")
return results
funcs = [str, int, lambda x: x / 0]
print(run_all(funcs, "42"))
# ["42", 42, "ERROR: division by zero"]