try/except в Python: шпаргалка
Карьерник — квиз-тренажёр в Telegram с 1500+ вопросами для собесов аналитика. SQL, Python, A/B, метрики. Бесплатно.
Базовый синтаксис
try:
# код, который может упасть
risky_operation()
except SomeError:
# что делать при ошибке
handle_error()Если в try возникло SomeError — управление передаётся в except. Если нет ошибки — except пропускается.
1. Самый частый паттерн
try:
value = int(input("Введите число: "))
except ValueError:
print("Это не число")2. Несколько типов ошибок
try:
result = data[key] / value
except KeyError:
print("Нет такого ключа")
except ZeroDivisionError:
print("Деление на ноль")Или одной строкой:
try:
...
except (KeyError, ZeroDivisionError):
print("Ошибка доступа или деления")3. Получить объект исключения
try:
risky_call()
except ValueError as e:
print(f"Ошибка: {e}")
print(f"Тип: {type(e).__name__}")4. finally — выполняется всегда
try:
file = open('data.csv')
process(file)
except FileNotFoundError:
print("Файла нет")
finally:
file.close() # выполнится и при успехе, и при ошибке5. else — выполняется если ошибки не было
try:
result = compute()
except ValueError:
print("Ошибка")
else:
print("Всё ок, result =", result)else выполняется только если в try не было исключения. Удобно отделить «обработку ошибки» от «что делать дальше».
6. Перевыбросить ошибку дальше
try:
risky_call()
except ValueError:
log_error("ValueError в risky_call")
raise # пробросить ту же ошибку дальшеИли выбросить другую:
try:
risky_call()
except ValueError as e:
raise RuntimeError(f"Не получилось: {e}") from efrom e сохраняет оригинальный traceback.
7. Пустой except — плохой стиль
# плохо — ловит вообще всё, включая KeyboardInterrupt
try:
...
except:
pass
# только немного лучше
try:
...
except Exception:
pass
# хорошо — ловить конкретные типы
try:
...
except (ValueError, TypeError) as e:
logger.error(e)8. try/except в функции
def safe_divide(a, b):
try:
return a / b
except ZeroDivisionError:
return None
safe_divide(10, 0) # None
safe_divide(10, 2) # 5.09. try/except в pandas
df = pd.read_csv('data.csv')
def safe_int(x):
try:
return int(x)
except (ValueError, TypeError):
return None
df['amount_int'] = df['amount'].apply(safe_int)В pandas часто лучше использовать pd.to_numeric(errors='coerce'):
df['amount_int'] = pd.to_numeric(df['amount'], errors='coerce')10. Контекстный менеджер (with) вместо try/finally
# старый способ
try:
f = open('data.csv')
data = f.read()
finally:
f.close()
# правильный способ
with open('data.csv') as f:
data = f.read()
# файл закроется автоматически11. Логирование ошибок
import logging
try:
risky_call()
except Exception as e:
logging.exception("Ошибка в risky_call")
# logging.exception автоматически добавляет traceback12. Кастомное исключение
class DataValidationError(Exception):
"""Ошибка валидации данных"""
pass
def validate(df):
if df.empty:
raise DataValidationError("Пустой DataFrame")
if df['amount'].isnull().any():
raise DataValidationError("NULL в amount")
try:
validate(df)
except DataValidationError as e:
print(f"Данные невалидны: {e}")13. Walrus + try в list comprehensions (не работает)
В list comp нельзя try/except. Нужна функция:
# нельзя
result = [int(x) try except None for x in values] # SyntaxError
# правильно — отдельная функция
def safe_int(x):
try: return int(x)
except: return None
result = [safe_int(x) for x in values]Типичные исключения
| Исключение | Когда возникает |
|---|---|
ValueError |
Некорректное значение (int("abc")) |
TypeError |
Неверный тип ("a" + 1) |
KeyError |
Нет ключа в dict |
IndexError |
Индекс за пределами list |
AttributeError |
Нет атрибута у объекта |
FileNotFoundError |
Файл не существует |
ZeroDivisionError |
Деление на 0 |
StopIteration |
Итератор закончился |
RuntimeError |
Общая runtime ошибка |
Exception |
Базовый класс всех |
EAFP vs LBYL
Два подхода:
# LBYL — Look Before You Leap
if key in d:
value = d[key]
# EAFP — Easier to Ask Forgiveness than Permission
try:
value = d[key]
except KeyError:
value = NoneВ Python обычно предпочитается EAFP — короче и часто быстрее (меньше двойных lookup).
Частые ошибки
Ошибка 1. Слишком широкий except
# плохо
try:
...
except Exception:
pass
# хорошо — явный тип
except (ValueError, KeyError) as e:
handle(e)Ошибка 2. Ловить и молча игнорировать
# плохо
try:
...
except:
pass # ошибку никто не увидит
# хоть логировать
try:
...
except Exception as e:
logger.warning(f"Ошибка: {e}")Ошибка 3. try вокруг огромного блока
# плохо — непонятно, где упадёт
try:
x = parse(data)
y = transform(x)
z = save(y)
notify(z)
except Exception:
handle()
# лучше — обернуть конкретную опасную операцию
x = parse(data) # может упасть отдельно
try:
z = save(y)
except DBError:
retry_save(y)Ошибка 4. except перед raise без сохранения цепочки
# плохо — теряем оригинальный traceback
try:
...
except ValueError:
raise RuntimeError("ошибка")
# правильно
except ValueError as e:
raise RuntimeError("ошибка") from eСвязанные темы
FAQ
Что быстрее: try/except или if?
Зависит. EAFP (try/except) быстрее, если ошибка редкая. LBYL (if) быстрее, если ошибка частая.
Когда использовать finally?
Для ресурсов, которые нужно освобождать (файлы, подключения). Но обычно with справляется элегантнее.
Чем отличается Exception от BaseException?
BaseException — корневой класс (включая KeyboardInterrupt, SystemExit). Exception — для «обычных» ошибок. Ловите Exception, не трогайте BaseException.
Как создать своё исключение?
Наследуйтесь от Exception или её подкласса:
class MyError(Exception):
passТренируйте Python — откройте тренажёр с 1500+ вопросами для собесов аналитиков.