Covil Do Dev

Tratamento de erros e exceções em Python

Aprenda neste artigo a como lidar com erros e exceções em Python. Você verá como gerar exceções e como tratá-las utilizando “try/except”.

Em Python, a execução de um programa é sempre encerrada quando se depara com um erro durante sua execução.

Um erro pode ser tanto de sintaxe(Syntax error) quanto uma exceção.

ad

Diferença entre erro de sintaxe e exceção

Um erro de sintaxe(Syntax error) é um erro na escrita do código, esse tipo de erro é fácil de ser detectado, pois a maioria das IDE modernas já avisam ao programador que o código está incorreto.

Abaixo temos um exemplo de um erro de sintaxe:

def dividir(a, b):    
    return a b  
  
  
dividir(2, 10)  

No exemplo acima o programador esqueceu de colocar o operador de divisão / entre as variáveis a e b, dessa forma, caso esse código seja executado o seguinte erro será exibido no terminal:

 File "teste.py", line 2 return a b ^SyntaxError: invalid syntax  

A seta indica onde o analisador encontrou o erro de sintaxe.

Neste exemplo basta adicionar o operador de divisão / entre a e b e o código seria executado sem problemas.

def dividir(a, b):    
    return a / b  
  
  
dividir(2, 10)  

Uma exceção ocorre quando o código está corretamente escrito, porém, devido a algum fator externo(um parâmetro enviado pelo usuário ou recebido a partir de outro processo) ou até mesmo interno(um caso não previsto), um erro acaba ocorrendo.

Um bom exemplo seria utilizando ainda a função de exemplo anterior, passar como parâmetros os valores 1 e 0, nesse caso, 1 será dividido por 0, e como todos sabem isso é impossível e acaba acontecendo um erro.

def dividir(a, b):    
    return a / b  
  
  
dividir(1, 0)  

Na execução, ocorre a seguinte exceção:

ZeroDivisionError: division by zero

Emitir uma exceção customizada

O Python por padrão já vem com várias exceções internas, mas em alguns casos é necessário emitir uma exceção especial, muito específica da função ou método em que você esteja trabalhando.

Para emitir a exceção, usamos a instrução raise quando determinada condição acontecer.

Por exemplo, caso a função só trabalhe com valores de a acima de 2, poderemos emitir uma exceção caso a seja menor ou igual(<=, ) a 2.

def funcao(a):  
    if a <= 2:  
        raise Exception('O valor de a deve ser maior que 2!')  
    ...

Chamando a função acima passando o valor de a como 1 teremos a seguinte saída:

Traceback (most recent call last):
  File "teste.py", line 6, in <module>
    funcao(1)
  File "teste.py", line 3, in funcao
    raise Exception('O valor de a deve ser maior que 2!')
Exception: O valor de a deve ser maior que 2!

Lidando com o erro

Nos exemplos anteriores vimos a diferença de erros e exceções e como emitir uma exceção, porém quando isso ocorre o programa acaba se encerrando, para evitar isso que veremos formas de lidar com as exceções.

Executando o código apenas caso o ambiente permita (AssertionError)

Uma das formas de lidar com erros é evitar que o programa execute em determinadas situações.

Por exemplo, caso o programa só funcione em Linux, independentemente do motivo, podemos fazer uma verificação e caso não esteja em um ambiente Linux encerramos o programa avisando o motivo para o usuário.

O Assert significa literalmente uma afirmação, ele afirma que determinada declaração é verdadeira, e caso não seja o programa é encerrado com a mensagem definida, como no exemplo abaixo:

import sys  
  
assert ('linux' in sys.platform), "Este programa só pode ser executado em um ambiente Linux!"  
  
print("COVIL DO DEV")

Executando o código no Windows, teremos a seguinte saída:

Traceback (most recent call last):
  File "teste.py", line 3, in <module>
    assert ('linux' in sys.platform), "Este programa só pode ser executado em um ambiente Linux!"
AssertionError: Este programa só pode ser executado em um ambiente Linux!

Agora caso executemos esse código no Linux, teremos a seguinte saída:

COVIL DO DEV

Dando alternativas caso ocorra exceções (Try/Except)

Nem sempre não executar o código seja a melhor opção, às vezes podemos lidar melhor e resolver essa exceção, para esses casos que utilizaremos essas duas instruções(try e except).

Essas instruções são usadas para capturar e lidar com o erro.

As instruções no bloco try são executadas como parte padrão do código, e caso ocorra algum erro ou exceção, o bloco except é então executado.

O exemplo abaixo exemplifica a utilização dessas duas instruções:

import sys  
  
  
def funcao():  
  assert ('linux' in sys.platform), "Este programa só pode ser executado em um ambiente Linux!"  
  print("COVIL DO DEV")  
  
try:  
    funcao()  
except:  
    ...

Nesse exemplo, temos algumas saídas possíveis.

Caso execute em uma máquina Linux:

COVIL DO DEV

Caso execute em uma máquina Windows:

A maneira como foi lidado com o erro foi não fazendo nada caso ele acontessesse(... não executa nada).

Por isso quando executamos o código no Windows temos uma saída vazia, porém o programa não foi encerrado.

Podemos exibir uma mensagem caso ocorra a exceção, alertando o usário de algo por exemplo.

import sys  
  
  
def funcao():  
  assert ('linux' in sys.platform), "Este programa só pode ser executado em um ambiente Linux!"  
  print("COVIL DO DEV")  
  
try:  
    funcao()  
except:  
    print("funcao não foi executado pois não se encontra em um ambiente Linux!")

Agora, executando novamente ainda teremos duas saídas possíveis.

Caso execute em uma máquina Linux:

COVIL DO DEV

Caso execute em uma máquina Windows:

funcao não foi executado pois não se encontra em um ambiente Linux!

Quando ocorre uma exceção em um programa que executa esta função, o programa continuará, apenas irá informar sobre o fato de que a execução da função não foi bem-sucedida.

Outra forma de exibir que ocorreu uma exceção é mostrando a mensagem de erro, sem emitir o erro, para isso poderiamos capturar a mensagem fazendo da seguinte forma:

import sys  
  
  
def funcao():  
  assert ('linux' in sys.platform), "Este programa só pode ser executado em um ambiente Linux!"  
  print("COVIL DO DEV")  
  
try:  
    funcao()  
except AssertionError as error:  
    print(error)

Agora, executando novamente continuamos tendo duas saídas possíveis.

Caso execute em uma máquina Linux:

COVIL DO DEV

Caso execute em uma máquina Windows:

Este programa só pode ser executado em um ambiente Linux!

No exemplo anterior, você chamou uma função que você mesmo escreveu.

Quando você executou a função, você capturou o AssertionError e imprimiu na tela.

Mas isso pode ser feita com qualquer função, abaixo um exemplo utilizando a função open() para abrir um aquivo:

try:
    with open('file.log') as file:
        read_data = file.read()
except:
    print("Não foi possível abrir o aquivo file.log")

Executando o programa sem o arquivo file.log na pasta, temos a seguinte saída:

Não foi possível abrir o aquivo file.log

Também podemos capturar essa exceção e exibir na tela(uma lista com todas as exceções pode ser encontrada na documentação do Python aqui):

try:
    with open('file.log') as file:
        read_data = file.read()
except FileNotFoundError as fnf_error:
    print(fnf_error)

Executando o programa sem o arquivo file.log na pasta, temos a seguinte saída:

[Errno 2] No such file or directory: 'file.log'

Podemos também tratar duas exeções que podem ocorrer no mesmo bloco de código dentro de try.

No exemplo abaixo estamos unindo os exemplos anteriores em um só.

import sys  
  
  
def funcao():  
  assert ('linux' in sys.platform), "Este programa só pode ser executado em um ambiente Linux!"  
  print("COVIL DO DEV")  
  
try:  
    funcao()  
    with open('file.log') as file:
        read_data = file.read()
except AssertionError as error:  
    print(error)
except FileNotFoundError as fnf_error:
    print(fnf_error)

Se o arquivo não existir, e este código for executado em uma máquina Windows, a saída será:

Este programa só pode ser executado em um ambiente Linux!

Agora se o arquivo não existir, e este código for executado em uma máquina Linux, a saída será:

[Errno 2] No such file or directory: 'file.log'

Caso o arquivo existir, e este código for executado em uma máquina Linux, a saída será:

COVIL DO DEV

Com isso, podemos entender que:

  • O código dentro do bloco try será executado até encontrar a primeira exceção.
  • O código dentro do bloco except será responsável por lidar com essa exceção.
  • Você pode antecipar várias exceções e diferenciar como o programa deve responder a elas.
  • Você pode usar um except genérico para todas as exceções possíveis, embora isso seja completamente não recomendado.

Cláusula Else

Podemos usar a instrução else para executar um bloco de código extra quando não ocorrer nenhuma das exceções previstas.

Usando o exemplo anterior, podemos adicionar um else e teremos a seguinte situação:

import sys  
  
  
def funcao():  
  assert ('linux' in sys.platform), "Este programa só pode ser executado em um ambiente Linux!"  
  print("COVIL DO DEV")  
  
try:  
    funcao()  
    with open('file.log') as file:
        read_data = file.read()
except AssertionError as error:  
    print(error)
except FileNotFoundError as fnf_error:
    print(fnf_error)
else:
	print("Nenhum erro ocorreu!")

Se o arquivo não existir, e este código for executado em uma máquina Windows, a saída será:

Este programa só pode ser executado em um ambiente Linux!

Agora se o arquivo não existir, e este código for executado em uma máquina Linux, a saída será:

[Errno 2] No such file or directory: 'file.log'

Caso o arquivo existir, e este código for executado em uma máquina Linux, a saída será:

COVIL DO DEV
Nenhum erro ocorreu!

Como o programa não encontrou nenhuma exceção, a cláusula else foi executada e exibiu a mensagem.

Cláusula finally

Também podemos colocar mais um bloco de código que sempre será executado, independente de ocorrer exceções ou não, isso é feito utilizando a cláusula finally.

Ainda com o exemplo anterior, podemos adicionar uma mensagem de encerramento do bloco:

import sys  
  
  
def funcao():  
  assert ('linux' in sys.platform), "Este programa só pode ser executado em um ambiente Linux!"  
  print("COVIL DO DEV")  
  
try:  
    funcao()  
    with open('file.log') as file:
        read_data = file.read()
except AssertionError as error:  
    print(error)
except FileNotFoundError as fnf_error:
    print(fnf_error)
else:
	print("Nenhum erro ocorreu!")
finally:
	print("Encerrando o bloco!")

Se o arquivo não existir, e este código for executado em uma máquina Windows, a saída será:

Este programa só pode ser executado em um ambiente Linux!
Encerrando o bloco!

Agora se o arquivo não existir, e este código for executado em uma máquina Linux, a saída será:

[Errno 2] No such file or directory: 'file.log'
Encerrando o bloco!

Caso o arquivo existir, e este código for executado em uma máquina Linux, a saída será:

COVIL DO DEV
Nenhum erro ocorreu!
Encerrando o bloco!

Tudo dentro do bloco finallyserá executado. Indepentemente se encontrou uma exceção ou se entrou na cláusula else.

Conclusão

Neste artigo foi visto sobre oque é uma exceção e sua diferença para um erro de sintaxe.

Foi visto também como se emitir uma exceção customizada e como lidar com as exceções quando elas ocorrerem.

Resumindo, temos as seguintes cláusulas para se lidar com exceções:

  • raise: permite lançar(ou emitir) uma exceção a qualquer momento.
  • assert: permite verificar se uma determinada condição é atendida e lançar uma exceção se não for.
  • try: todas as instruções são executadas até que uma exceção seja encontrada.
  • except: é usado para capturar e manipular as exceções encontradas na cláusula try.
  • else: permite preparar um bloco de código que deve ser executado somente quando nenhuma exceção for encontrada na cláusula try.
  • finally: permite preparar um bloco de código que deve ser executado sempre, com ou sem exceções encontradas anteriormente.

Obrigado por visitar o blog e por ler esse artigo, se tive qualquer dúvida, ideia ou sugestão, não hesite em entrar em contato pelo meu e-mail: lindomar@covildodev.com.br