← Назад к вопросам

Как перехватить исключения в Python?

1.0 Junior🔥 301 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Обработка исключений в Python

Обработка исключений (exception handling) — это критический инструмент для написания надежного и устойчивого к ошибкам кода. Python предоставляет мощный механизм try-except-finally.

1. Базовый синтаксис try-except

# Базовая структура
try:
    # Код, который может вызвать исключение
    result = 10 / 0
except ZeroDivisionError:
    # Обработка конкретного исключения
    print("Нельзя делить на ноль!")

# Результат: печатает сообщение об ошибке вместо краша

2. Перехват нескольких исключений

try:
    value = int("abc")  # ValueError
except ValueError:
    print("Ошибка: неверное значение")
except TypeError:
    print("Ошибка: неверный тип")
except Exception as e:
    print(f"Неожиданная ошибка: {e}")

Порядок важен — специфичные исключения должны идти первыми.

3. Несколько исключений в одном блоке

try:
    value = int("abc")
except (ValueError, TypeError) as e:
    print(f"Ошибка: {e}")

4. Блок else

Код в else выполняется, если исключения не было:

try:
    number = int("123")
except ValueError:
    print("Не число")
else:
    print(f"Число: {number}")  # Печатается только если не было ошибки

5. Блок finally

Код в finally выполняется ВСЕГДА (даже если было исключение):

try:
    file = open("data.txt")
    data = file.read()
except FileNotFoundError:
    print("Файл не найден")
finally:
    file.close()  # Выполнится в любом случае

Обычно используется для очистки ресурсов.

6. Менеджер контекста (context manager)

Автоматически закрывает ресурсы (лучше чем finally):

# Без with — нужен finally
file = open("data.txt")
try:
    data = file.read()
except FileNotFoundError:
    print("Файл не найден")
finally:
    file.close()

# С with — автоматическое закрытие
with open("data.txt") as file:
    data = file.read()  # Файл закроется автоматически

7. Иерархия исключений

Все исключения в Python наследуются от BaseException:

# Иерархия
BaseException
├── SystemExit
├── KeyboardInterrupt
└── Exception
    ├── StopIteration
    ├── GeneratorExit
    ├── ArithmeticError
    │   ├── ZeroDivisionError
    │   └── OverflowError
    ├── LookupError
    │   ├── IndexError
    │   └── KeyError
    ├── NameError
    ├── TypeError
    ├── ValueError
    ├── RuntimeError
    └── ... (еще много)

# ✅ Перехватывай Exception, не BaseException
try:
    value = int("abc")
except Exception as e:  # Ловит все Exception подклассы
    print(f"Ошибка: {e}")

# ❌ Не перехватывай BaseException
# except BaseException:  # Ловит и KeyboardInterrupt!

8. Создание пользовательских исключений

# Простое исключение
class InvalidUserError(Exception):
    pass

# Исключение с дополнительной информацией
class ValidationError(Exception):
    def __init__(self, field, message):
        self.field = field
        self.message = message
        super().__init__(f"Ошибка {field}: {message}")

# Использование
try:
    if not username:
        raise ValidationError("username", "не может быть пустым")
except ValidationError as e:
    print(f"Ошибка: {e.message}")

9. Цепочка исключений (exception chaining)

Сохрани оригинальное исключение при выбросе нового:

try:
    result = 10 / 0
except ZeroDivisionError as e:
    # Выбрось новое исключение, сохраняя информацию о старом
    raise ValueError("Неверное число") from e

# Результат:
# ValueError: Неверное число
# The above exception was the direct cause of the following exception:
# ZeroDivisionError: division by zero

Без from e оригинальная ошибка может быть потеряна.

10. Получение информации об ошибке

import traceback

try:
    result = 10 / 0
except Exception as e:
    # Информация об исключении
    print(f"Тип: {type(e).__name__}")
    print(f"Сообщение: {str(e)}")
    print(f"Args: {e.args}")
    
    # Полная информация о стеке
    print(traceback.format_exc())

11. Перехват и переброс

try:
    data = fetch_data_from_api()
except requests.ConnectionError as e:
    print(f"Ошибка подключения: {e}")
    # Переброс исключения дальше
    raise  # Выбросит то же исключение

# Или переброс с логированием
import logging

try:
    dangerous_operation()
except Exception as e:
    logging.error(f"Ошибка: {e}", exc_info=True)
    raise  # Логируем и переидаем ошибку дальше

12. Условная обработка

try:
    result = calculate(value)
except ValueError as e:
    if "invalid" in str(e):
        print("Неверное значение")
    elif "out of range" in str(e):
        print("Значение вне диапазона")
    else:
        raise  # Если не знаем как обработать

13. Практический пример: API запрос с обработкой ошибок

import requests
from typing import Optional

def fetch_user(user_id: int) -> Optional[dict]:
    try:
        response = requests.get(f"https://api.example.com/users/{user_id}", timeout=5)
        response.raise_for_status()  # Выбросит HTTPError если статус ошибки
        return response.json()
    
    except requests.ConnectionError:
        print("Ошибка подключения")
        return None
    
    except requests.Timeout:
        print("Timeout — сервер не ответил")
        return None
    
    except requests.HTTPError as e:
        if e.response.status_code == 404:
            print("Пользователь не найден")
        elif e.response.status_code == 401:
            print("Не авторизован")
        else:
            print(f"HTTP ошибка: {e.response.status_code}")
        return None
    
    except ValueError as e:
        print(f"Ошибка парсинга JSON: {e}")
        return None

14. Обработка исключений в циклах

# ❌ Неправильно — пропустит весь цикл
try:
    for item in items:
        process(item)
except Exception:
    print("Ошибка")

# ✅ Правильно — продолжит цикл
for item in items:
    try:
        process(item)
    except Exception as e:
        print(f"Ошибка для {item}: {e}")
        continue

15. Контекстный менеджер для управления исключениями

from contextlib import suppress, contextmanager

# suppress — игнорирует исключение
from contextlib import suppress
with suppress(FileNotFoundError):
    os.remove("nonexistent.txt")  # Ошибка будет проигнорирована

# Кастомный менеджер контекста
@contextmanager
def safe_operation(name):
    try:
        print(f"Начало: {name}")
        yield
    except Exception as e:
        print(f"Ошибка в {name}: {e}")
    finally:
        print(f"Конец: {name}")

with safe_operation("wichtige операция"):
    result = 10 / 0  # Будет обработана

Лучшие практики

Ловй специфичные исключения — не Exception или BaseException ✅ Используй except Exception — для неожиданных ошибок ✅ Используй finally — для очистки ресурсов ✅ Используй with — вместо try-finally для файлов ✅ Цепочка исключений — используй from для контекста ✅ Логирование — логируй исключения с трассировкой стека ✅ Переброс исключений — если не можешь их обработать ✅ Создавай свои исключения — для специфичных ошибок ✅ Не молчи об ошибках — всегда логируй или выбрасывай

Правильная обработка исключений делает код надежным и легко отлаживаемым.

Как перехватить исключения в Python? | PrepBro