Exceções: de onde vêm, para onde vão e como organizá-las em Python

Rafael Tardivo
rafaeltardivo
Published in
3 min readApr 10, 2020

Quando e como tratar exceções e a importância dos tratamentos especializados.

créditos da imagem: https://tinyurl.com/sr6eelw

Antes de mais nada, o que são exceções?

Podemos dizer que exceções são resultado de “eventos excepcionais” ocorridos durante o fluxo regular de um software.

Como assim?

Em termos práticos, se algo deu errado, uma exceção que corresponde ao problema ocorrido será lançada.

Um exemplo do mundo real:

Imagine que você acabou de clicar no botão “imprimir” de um PDF, sua impressora está ligada, configurada e com papel. No entanto, você percebe que a impressão não foi realizada e se depara com a seguinte mensagem:

IMPRESSORA SEM TINTA!

Pois é, você provavelmente já passou por isso! O fluxo normal seria imprimir o documento, mas algo aconteceu e esse fluxo foi interrompido… Em outras palavras, uma exceção ocorreu.

Um exemplo em Python

Vamos imaginar que estamos escrevendo o trecho de código responsável pelo processo de impressão:

try:
print_document(document)
except OutOfInkError:
display_message("IMPRESSORA SEM TINTA")

O exemplo acima nos diz: tente (try) imprimir, caso a impressora esteja sem tinta (except OutOfInkError), exiba no display a mensagem IMPRESSORA SEM TINTA!.

Múltiplas Exceções

Concorda comigo que faltar tinta não é o único possível erro em um processo de impressão? A impressora poderia, por exemplo, ter tinta e não ter papel!

Como você já deve imaginar, podemos nos preparar para mais de uma exceção:

try:
print_document(document)
except OutOfInkError:
display_message("IMPRESSORA SEM TINTA!")
except OutOfPaperError:
display_message("IMPRESSORA SEM PAPEL!")

Hierarquia de Exceções

Exceções geralmente são definidas de maneira hierárquica e conhecer essa hierarquia é extremamente importante para nós. Vejamos por exemplo, uma versão da hierarquia de exceções built-in do Python:

?

Observe o seguinte exemplo de hierarquia: AttributeError herda de Exception, que por sua vez herda de BaseException.

Na prática, o que isso muda?

Voltando ao nosso exemplo de impressão, vamos imaginar que nossas exceções OutOfInkError e OutOfPaperError herdam de PrintError, que por sua vez (assim como todas exceções em Python), herda de Exception:

            Exception
^
|
|
PrintError
^ ^
| |
| |
OutOfInkError OutOfPaperError

Em Programação Orientada a Objetos, um objeto sempre passará no teste É- Um de uma classe pai, ou seja:

?OutOfInkError É Um PrintError
PrintError
É Um Exception

Um exemplo mais lúdico seria a relação entre as classes Animal e Cachorro:

   Animal
^
|
|
Cachorro

Concorda que todo cachorro É-Um animal? Em contrapardida, nem todo animal É-Um cachorro, certo? (Caso não tenha entendido o exemplo, dê uma olhada aqui)

A ordem dos fatores altera o produto

Se tratando de exceções, a ordem faz MUITA diferença! As exceções são tratadas de acordo com a ordem de seus blocos e é aí que entra a relacão É-Um.

É-Um

Supondo que agora as exceções do nosso processo de impressão sejam tratadas da seguinte maneira:

try:
print_document(document)
except PrintError:
display_message("ERRO AO IMPRIMIR DOCUMENTO!")
except OutOfInkError:
display_message("IMPRESSORA SEM TINTA!")
except OutOfPaperError:
display_message("IMPRESSORA SEM PAPEL!")

As exceções OutOfInkError e OutOfPaperError nunca seriam tratadas! Ambas seriam tratadas como:

ERRO AO IMPRIMIR DOCUMENTO!

O motivo? Ambas passam no teste É-Um do tratamento de PrintError.

Visibilidade

O ponto chave para o tratamento de exceções específicas é: visibilidade.

Como você saberá se precisa comprar tinta ou papel se a única informação disponível é: ERRO AO IMPRIMIR DOCUMENTO?

O mesmo se aplica ao seu software! Saber exatamente o que aconteceu fará com que tempo e esforço empregados para conter o incidente sejam significamente menores ;)

Conclusão

  • Conheça a hieraquia de exceções da linguagem de programação em uso;
  • A ordem importa: da mais específica para a mais generalizada, SEMPRE;
  • Evite tratamentos excessivamente genéricos, você pode acabar suprimindo exceções que não deveria.

EXTRA: O (excelente) site realpython tem um artigo bem bacana sobre um anti-pattern amplamente usado em Python: https://realpython.com/the-most-diabolical-python-antipattern/

Vale a pena ler!

CYA :)

--

--