← Назад к вопросам
В чем разница между ошибкой и исключением?
1.3 Junior🔥 231 комментариев
#Python Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между ошибками и исключениями в Python
В Python концепции "ошибка" и "исключение" связаны, но имеют различия. Оба являются подклассами встроенного класса BaseException, но используются для разных целей и обрабатываются по-разному.
Иерархия исключений в Python
BaseException
├── SystemExit # Выход из программы (sys.exit())
├── KeyboardInterrupt # Ctrl+C
├── GeneratorExit # Выход из генератора
└── Exception # Базовый класс для всех обычных исключений
├── StopIteration # Конец итератора
├── ArithmeticError # Математические ошибки
│ ├── ZeroDivisionError
│ ├── FloatingPointError
│ └── OverflowError
├── LookupError # Ошибки доступа
│ ├── IndexError
│ └── KeyError
├── TypeError # Неверный тип данных
├── ValueError # Неверное значение
├── AttributeError # Нет атрибута
├── NameError # Переменная не определена
├── RuntimeError # Ошибки выполнения
└── ... (и множество других)
Определение: Ошибки (Errors)
Ошибки — это исключения, которые обычно не следует обрабатывать в пользовательском коде. Они указывают на серьёзные проблемы в системе или среде выполнения. Примеры:
SystemExit— явный выход программыKeyboardInterrupt— прерывание пользователем (Ctrl+C)GeneratorExit— выход из генератораMemoryError— недостаточно памятиStackOverflowError— переполнение стекаImportError— ошибка импорта модуля
Определение: Исключения (Exceptions)
Исключения — это события, которые изменяют нормальный ход выполнения программы. Они могут и должны быть обработаны в пользовательском коде. Примеры:
ValueError— неверное значениеTypeError— неверный тип данныхKeyError— ключ не найден в словареIndexError— индекс вне границ спискаFileNotFoundError— файл не найденConnectionError— ошибка соединения
Практическое различие
# ❌ Ошибка - обрабатывать НЕ нужно (нет смысла)
try:
sys.exit(0) # SystemExit
except SystemExit:
pass # Это плохая практика - программа должна завершиться
# ✅ Исключение - обрабатываем (имеет смысл)
try:
result = 10 / 0 # ZeroDivisionError
except ZeroDivisionError:
print("Нельзя делить на ноль!")
result = 0 # Обработали ошибку и продолжили
# ❌ Неправильно - ловим ошибку системы
try:
# Кто-то случайно удалил файл БД
with open(/data/important.db) as f:
data = f.read()
except FileNotFoundError:
# Это исключение, его МОЖНО обрабатывать
pass
# ✅ Правильно - ловим системную ошибку только когда нужно
try:
import critical_module
except ImportError as e:
# Предупредим, но программа может работать без этого модуля
print(f"Warning: {e}")
Различия в таблице
| Аспект | Ошибка | Исключение |
|---|---|---|
| Наследуется от | Error (подкласс BaseException) | Exception (подкласс BaseException) |
| Обрабатываемость | Не должна обрабатываться | Должна обрабатываться |
| Причина | Серьёзные проблемы в системе | Предсказуемые проблемы в коде |
| Примеры | SystemExit, KeyboardInterrupt | ValueError, TypeError |
| Обычный блок try-except | except Exception их не ловит | except Exception их ловит |
Частая ошибка: ловить слишком много
# ❌ Плохо - ловим ВСЁ, включая ошибки системы
try:
user_input = input("Введите число: ")
number = int(user_input)
result = 100 / number
except: # Bare except ловит даже SystemExit!
print("Что-то пошло не так")
# ✅ Хорошо - ловим только ожидаемые исключения
try:
user_input = input("Введите число: ")
number = int(user_input)
result = 100 / number
except (ValueError, ZeroDivisionError) as e:
print(f"Некорректный ввод: {e}")
# ✅ Ещё лучше - обрабатываем разные случаи по-разному
try:
user_input = input("Введите число: ")
number = int(user_input)
result = 100 / number
except ValueError:
print("Пожалуйста, введите целое число")
except ZeroDivisionError:
print("Невозможно делить на ноль")
except Exception as e: # Только для неожиданных исключений
print(f"Непредвиденная ошибка: {e}")
raise # Пробросим дальше
Создание собственных исключений
# ✅ Пользовательское исключение (наследуется от Exception)
class InsufficientFundsError(Exception):
"""Исключение для случая, когда недостаточно средств."""
pass
class AccountError(Exception):
"""Базовое исключение для всех ошибок аккаунта."""
pass
class NegativeBalanceError(AccountError):
"""Специфическое исключение при отрицательном балансе."""
pass
class BankAccount:
def __init__(self, balance: float):
self.balance = balance
def withdraw(self, amount: float):
if amount > self.balance:
raise InsufficientFundsError(
f"Недостаточно средств. Требуется {amount}, "
f"доступно {self.balance}"
)
self.balance -= amount
def set_balance(self, amount: float):
if amount < 0:
raise NegativeBalanceError(
"Баланс не может быть отрицательным"
)
self.balance = amount
# Использование
try:
account = BankAccount(100)
account.withdraw(150)
except InsufficientFundsError as e:
print(f"Ошибка: {e}")
Best Practices
# ✅ Принцип EAFP (Easier to Ask for Forgiveness than Permission)
# В Python предпочитают ловить исключения, чем проверять условия
# Плохо - Pythonic не нужно проверять наличие ключа
if key in my_dict:
value = my_dict[key]
# Хорошо - просто ловим исключение если ключа нет
try:
value = my_dict[key]
except KeyError:
value = None # или дефолт значение
Понимание разницы между ошибками и исключениями критично для написания надёжного и правильно обрабатывающего ошибки кода.