Что произойдёт, если в блоке `finally` выбросить исключение, а в блоке `except` оно уже было перехвачено?

Если исключение выбрасывается в блоке finally после того, как исключение было перехвачено в блоке except, то исключение из блока finally заменит собой исходное исключение, перехваченное в except. Это значит, что исходное исключение будет потеряно, и обработчик, который ждал исходное исключение, его не получит. Важно избегать выброса исключений в finally блоке, если это возможно.

Если в блоке finally выбрасывается исключение, а в блоке except уже было перехвачено исключение, то вот что произойдет:

  1. Исключение из блока except будет потеряно. Исключение, которое было поймано в блоке except и могло быть важным для дальнейшей обработки, будет проигнорировано.
  2. Исключение из блока finally будет распространено. Вместо него будет обработано исключение, возникшее в finally блоке. Это может привести к непредсказуемому поведению программы, так как исходная причина ошибки будет замаскирована новым исключением.
  3. Код, следующий за блоком try...except...finally, будет выполняться с учетом исключения, выброшенного из finally. То есть, программа продолжит выполнение, но уже в контексте нового исключения.

Пример:


  def example():
    try:
      print("Начало try")
      raise ValueError("Ошибка в try")
    except ValueError as e:
      print(f"Поймано исключение ValueError: {e}")
      raise TypeError("Новая ошибка в except")  # Перехватываем ValueError и выбрасываем TypeError
    finally:
      print("Блок finally")
      raise OSError("Ошибка в finally")  # Выбрасываем OSError

  try:
    example()
  except OSError as e:
    print(f"Поймано исключение OSError: {e}")
  except TypeError as e:
    print(f"Поймано исключение TypeError: {e}")

  print("Конец программы")
  

Вывод этого кода:

  Начало try
  Поймано исключение ValueError: Ошибка в try
  Блок finally
  Поймано исключение OSError: Ошибка в finally
  Конец программы
  

В этом примере:

  • Изначально выбрасывается ValueError в блоке try.
  • Этот ValueError перехватывается в блоке except.
  • В блоке except мы выбрасываем TypeError, но он перекроется исключением из finally.
  • В блоке finally выбрасывается OSError.
  • В итоге, распространяется только OSError, и TypeError из except игнорируется.

Важно: Избегайте выбрасывания исключений в блоке finally, если это не абсолютно необходимо. Лучше обработать ошибку до finally или логировать ее. Выбрасывание исключения в finally может скрыть важные детали исходной ошибки и затруднить отладку.

0