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.
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 finally
será 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áusulatry
.else
: permite preparar um bloco de código que deve ser executado somente quando nenhuma exceção for encontrada na cláusulatry
.finally
: permite preparar um bloco de código que deve ser executado sempre, com ou sem exceções encontradas anteriormente.