Hierarquia de Exceções

Em Python, todas as exceções derivam da classe BaseException. Isso significa que toda exceção em Python é uma instância de BaseException ou de uma de suas subclasses.
A classe BaseException é a classe de nível mais alto na hierarquia de exceções. Ela fornece alguns métodos comuns que todas as exceções podem usar, como __str__ e __repr__. Entretanto, não é recomendado usar BaseException diretamente no seu código, pois ela é muito abrangente e pode capturar qualquer tipo de exceção. Em vez disso, utilize classes de exceção mais específicas que sejam subclasses de BaseException. O Python oferece várias classes de exceção integradas que você pode aproveitar, e também é possível criar suas próprias classes de exceção personalizadas:
BaseException
 ├── BaseExceptionGroup
 ├── GeneratorExit
 ├── KeyboardInterrupt
 ├── SystemExit
 └── Exception
      ├── ArithmeticError
      │    ├── FloatingPointError
      │    ├── OverflowError
      │    └── ZeroDivisionError
      ├── AssertionError
      ├── AttributeError
      ├── BufferError
      ├── EOFError
      ├── ExceptionGroup [BaseExceptionGroup]
      ├── ImportError
      │    └── ModuleNotFoundError
      ├── LookupError
      │    ├── IndexError
      │    └── KeyError
      ├── MemoryError
      ├── NameError
      │    └── UnboundLocalError
      ├── OSError
      │    ├── BlockingIOError
      │    ├── ChildProcessError
      │    ├── ConnectionError
      │    │    ├── BrokenPipeError
      │    │    ├── ConnectionAbortedError
      │    │    ├── ConnectionRefusedError
      │    │    └── ConnectionResetError
      │    ├── FileExistsError
      │    ├── FileNotFoundError
      │    ├── InterruptedError
      │    ├── IsADirectoryError
      │    ├── NotADirectoryError
      │    ├── PermissionError
      │    ├── ProcessLookupError
      │    └── TimeoutError
      ├── ReferenceError
      ├── RuntimeError
      │    ├── NotImplementedError
      │    └── RecursionError
      ├── StopAsyncIteration
      ├── StopIteration
      ├── SyntaxError
      │    └── IndentationError
      │         └── TabError
      ├── SystemError
      ├── TypeError
      ├── ValueError
      │    └── UnicodeError
      │         ├── UnicodeDecodeError
      │         ├── UnicodeEncodeError
      │         └── UnicodeTranslateError
      └── Warning
           ├── BytesWarning
           ├── DeprecationWarning
           ├── EncodingWarning
           ├── FutureWarning
           ├── ImportWarning
           ├── PendingDeprecationWarning
           ├── ResourceWarning
           ├── RuntimeWarning
           ├── SyntaxWarning
           ├── UnicodeWarning
           └── UserWarning
The hierarchy of built-in exception classes in Python (from the official Python docs).
Isso significa que FileNotFoundError é uma subclasse de OSError, que por sua vez é uma subclasse de Exception, a qual herda de BaseException.

Respeitando a hierarquia de exceções

Ao usar múltiplos except, é importante respeitar a hierarquia de exceções do Python. Isso significa que, se você capturar uma classe de exceção base, como Exception, deve capturar as exceções mais específicas antes dela. Caso escreva um except de uma classe mais específica depois de um except para a classe base, o bloco desse except mais específico não será executado:
try:
    # algum código que pode gerar uma exceção
except ValueError:
    # lidando com ValueError
except Exception:
    # lidando com qualquer outra exceção
Neste exemplo, a exceção ValueError é tratada primeiro. Se o código gerar qualquer outra exceção derivada de Exception, o segundo bloco except será executado. No entanto, não é recomendável capturar Exception diretamente, pois é muito abrangente e pode capturar qualquer tipo de exceção. É melhor capturar exceções mais específicas sempre que possível:
try:
    ...
except TypeError:
    ...
except ValueError:
    ...
except Exception:
    ...
Se o código dentro do bloco try gerar um TypeError ou ValueError, o respectivo bloco except será executado. Se for gerada outra exceção que derive de Exception, o código no terceiro bloco except será chamado.
Se colocarmos a exceção base como o primeiro bloco except, ela impedirá que os demais sejam executados:
try:
    # algum código que pode gerar uma exceção
except Exception as e:               # Isso vai capturar todos os erros
    print(f'An error occurred: {e}')
except ValueError:                   # Nunca será executado
    print('A ValueError occurred')
except TypeError:                    # Nunca será executado
    print('A TypeError occurred')
Neste exemplo, o bloco try pode gerar qualquer tipo de exceção. No entanto, o primeiro except captura a classe base Exception, então ele pegará qualquer exceção que seja gerada. A mensagem de erro será impressa e os demais blocos except não serão executados.

Desafio: Analisar o Ficheiro

Você está trabalhando como engenheiro de software em uma startup que lida com grandes quantidades de dados. Recentemente, a equipe decidiu utilizar arquivos JSON para armazenar e processar essas informações. Esses dados são fundamentais para as operações da sua startup, e sua tarefa é escrever um programa em Python que leia e analise esses arquivos JSON.
Contudo, devido ao grande volume de dados e por haver várias pessoas trabalhando neles, alguns erros ocorrem com frequência:
  1. Às vezes, o arquivo de dados não existe.
  1. Às vezes, o arquivo de dados está vazio.
  1. Às vezes, o arquivo de dados contém conteúdo que não é JSON válido.
É preciso garantir que o seu programa em Python consiga lidar com essas exceções sem travar e fornecer mensagens de erro claras, para que a equipe de dados possa identificar e corrigir o problema rapidamente.
Seu programa deve receber como entrada uma string que representa o nome do arquivo e lidar com os seguintes cenários:
  • Se o arquivo não existe, ele deve gerar FileNotFoundError e imprimir uma mensagem de erro apropriada.
  • Se o arquivo está vazio, ele deve gerar ValueError e imprimir uma mensagem de erro apropriada.
  • Se o conteúdo do arquivo não for JSON válido, ele deve gerar json.JSONDecodeError (que é uma subclasse de ValueError) e imprimir uma mensagem de erro apropriada. Ao gerar essa exceção, você deve fornecer os atributos doc e pos como parâmetros.
💡
except json.JSONDecodeError as e:
Cada uma dessas exceções deve ser tratada independentemente das outras, e o seu programa deve exibir uma mensagem de erro específica para cada caso.
Entrada
Saída
nonexistent_file.json
FileNotFoundError: File 'nonexistent_file.json' does not exist.
empty_file.json
ValueError: File 'empty_file.json' is empty.
invalid_json.json
JSONDecodeError: Content of file 'invalid_json.json' is not valid JSON.: line 1 column 1 (char 0)
success.json
File 'success.json' has been successfully parsed as valid JSON.
 

Constraints

Time limit: 2 seconds

Memory limit: 512 MB

Output limit: 1 MB

To check your solution you need to sign in
Sign in to continue