Конструкция try-except: эффективное управление ошибками в коде Python
Обработка исключений с try except в Python
Конструкция try except позволяет перехватывать и обрабатывать ошибки, возникающие во время выполнения программы. Это предотвращает аварийное завершение и даёт возможность корректно отреагировать на исключительную ситуацию.
Базовый синтаксис try except
Самый простой способ – обернуть потенциально опасный код в блок try, а в except указать, как реагировать на любую ошибку.
try:
number = int(input("Введите число: "))
print(100 / number)
except:
print("Произошла ошибка")Try error python (ошибка try-except в python)
Если пользователь введёт не число или ноль, программа не упадёт, а выведет сообщение. Недостаток – перехватываются все исключения, включая SystemExit и KeyboardInterrupt, что не всегда желательно.
Как перехватить только определённые типы ошибок в Python?
Указываем конкретный класс исключения после except. Так обрабатывается только ожидаемая ситуация, а остальные ошибки продолжают всплывать.
try:
value = int(input("Введите целое число: "))
except ValueError:
print("Введено не число")Типичная ошибка:
Перехват Exception слишком широкий. Лучше указывать конкретные типы. Если нужно несколько – перечислите их в кортеже: except (ValueError, ZeroDivisionError):.
Как получить доступ к объекту исключения и его сообщению?
Используем as e – переменная, в которую помещается экземпляр исключения.
try:
result = 1 / 0
except ZeroDivisionError as e:
print(f"Ошибка: {e}")Как выполнить код, если исключение не возникло (блок else)?
Блок else выполняется, только когда в try не было ошибок. Это отделяет успешный сценарий от обработки ошибок.
try:
number = int(input("Число: "))
except ValueError:
print("Не число")
else:
print(f"Вы ввели {number}")Как гарантировать выполнение кода независимо от результата (блок finally)?
finally выполняется всегда – после try, except или else, даже если возникло исключение, не обработанное except. Используется для закрытия файлов, освобождения ресурсов.
try:
f = open("file.txt", "r")
data = f.read()
except FileNotFoundError:
print("Файл не найден")
finally:
f.close()Распространённая проблема:
Забывают про finally при работе с файлами, что может привести к утечке дескрипторов. Всегда закрывайте ресурсы в finally или используйте менеджеры контекста with.
Как обработать несколько исключений по-разному?
Можно написать несколько блоков except для разных типов. Важен порядок – от более конкретных к общим.
try:
x = int(input("x: "))
y = int(input("y: "))
result = x / y
except ValueError:
print("Ошибка преобразования")
except ZeroDivisionError:
print("Деление на ноль")
except Exception as e:
print(f"Неизвестная ошибка: {e}")Ошибки при множественных except:
Если поставить except Exception первым, он перехватит все частные случаи. Всегда располагайте конкретные исключения выше общих.
Как повторно возбудить исключение после обработки?
Используется raise без аргументов внутри блока except. Это позволяет залогировать ошибку и всё равно передать её выше.
try:
risky_operation()
except ValueError as e:
print("Ошибка, логируем...")
raiseКак создать собственное исключение и обработать его?
Наследуемся от Exception и используем в try except.
class NegativeError(Exception):
pass
def check_positive(value):
if value < 0:
raise NegativeError("Число отрицательное")
return value
try:
check_positive(-5)
except NegativeError as e:
print(e)Проблема:
Перехват Exception без необходимости скрывает ошибки проектирования. Создавайте свои исключения только если это действительно улучшает читаемость кода.
Расширенные примеры работы с try except
Пример 1. Вложенные try-блоки и finally
Внутренний блок обрабатывает конкретную ошибку, внешний – более общую. Finally срабатывает даже при необработанном исключении.
def read_and_divide(filename):
try:
f = open(filename, 'r')
try:
data = f.read().strip()
if not data:
raise ValueError("Файл пуст")
num = int(data)
result = 100 / num
print(f"Результат: {result}")
except ValueError as e:
print(f"Ошибка данных: {e}")
finally:
f.close()
print("Файл закрыт")
except FileNotFoundError:
print("Файл не найден")
# Проверка
read_and_divide("numbers.txt")# Если numbers.txt содержит "10": # Результат: 10.0 # Файл закрыт # Если файла нет: # Файл не найден # Если в файле "abc": # Ошибка данных: invalid literal for int() with base 10: 'abc' # Файл закрыт
Пример 2. Отлов нескольких типов исключений с разными действиями и логирование
import sys
def safe_division(a, b):
try:
result = a / b
except TypeError as e:
print(f"Тип не подходит: {e}", file=sys.stderr)
return None
except ZeroDivisionError:
print("Деление на ноль", file=sys.stderr)
return None
else:
return result
print(safe_division(10, 2)) # 5.0
print(safe_division(10, 0)) # None
print(safe_division("10", 2)) # None5.0 Деление на ноль None Тип не подходит: unsupported operand type(s) for /: 'str' and 'int' None
Пример 3. Создание собственного исключения с дополнительной информацией
class CustomError(Exception):
def __init__(self, message, code):
super().__init__(message)
self.code = code
def process(value):
if value < 0:
raise CustomError("Неверное значение", code=400)
return value * 2
try:
process(-1)
except CustomError as e:
print(f"Ошибка #{e.code}: {e}")Ошибка #400: Неверное значение
Пример 4. Перехват исключения с замыканием (raise from)
Цепочка исключений помогает сохранить контекст первоначальной ошибки.
def get_data(url):
try:
response = requests.get(url)
response.raise_for_status()
except requests.ConnectionError as e:
raise RuntimeError("Не удалось подключиться") from e
try:
get_data("http://несуществующий.сайт.ру")
except RuntimeError as e:
print(f"Ошибка: {e}")
# e.__cause__ содержит исходное исключение ConnectionErrorОшибка: Не удалось подключиться
Пример 5. Использование try except для выхода из глубокой рекурсии
def factorial(n):
if n < 0:
raise ValueError("Факториал отрицательного числа не определён")
if n == 0:
return 1
# Намеренная ошибка для демонстрации
if n > 900:
raise RecursionError("Слишком глубокий вызов")
return n * factorial(n-1)
try:
print(factorial(10))
except (ValueError, RecursionError) as e:
print(f"Ошибка расчёта: {e}")3628800