Básico sobre tratamento de exceções em Python 3.4

Resolvi fazer um básico sobre Python, que ainda não domino completamente, mas de todas as linguagens que já vi, foi a que eu mais gostei, pois une poder a simplicidade.

[ Hits: 16.010 ]

Por: Perfil removido em 26/02/2015


Introdução



Resolvi fazer um básico sobre Python, que ainda não domino completamente, mas de todas as linguagens que já vi, foi a que eu mais gostei, pois une poder a simplicidade.

Bom, vamos lá então.

O que é o tratamento de exceções?

Sem copiar textos de outros lugares, para entender o tratamento de exceções, precisamos entender o que é uma exceção dentro da programação.
Linux: Básico sobre tratamento de exceções em Python 3.4
Uma exceção é algo que saía fora do planejado, por exemplo, você querer somar dois números, mas acabar inserindo uma letra e um número, irá gerar um erro, esse erro é a chamada exceção. Exceções muitas vezes são feias, visualmente falando, e acabam trazendo informações desnecessárias ao usuário final e algumas vezes causam até o vazamento de informações.

O tratamento de exceções é basicamente filtrar esses erros "feios", que costumam apresentar informações mais técnicas, para ajudar o programador a encontrar o erro, e exibir somente uma mensagem mais amigável e talvez com apenas um código do erro.

Na prática...

Um script simples para somar 2 números:

python
>>> N1 = 25
>>> N2 = 'asd'
>>> N1 + N2
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    N1 + N2
TypeError: unsupported operand type(s) for +: 'int' and 'str'


Essa:

Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    N1 + N2
TypeError: unsupported operand type(s) for +: 'int' and 'str'


É a exceção, que informa ali a linha onde ocorreu o erro e o tipo, isso é feio para o usuário e na maioria das vezes só vai confundi-lo, então vamos usar o chamado tratamento de exceções. Em Python, assim como em muitas linguagens, ele é feito na sua forma mais básica com try e except.

Sua sintaxe é semelhante a muitas linguagens de alto de nível:

try:
   comandos
except:
   comandos que deverão ser executados caso de algo errado

Voltando a código ali de cima, vamos filtrar esse erro:

>>> N1 = 25
>>> N2 = 'asd'
>>> try:
    N1 + N2
except:
    print('erro ao tentar realizar a soma')


Executando:

erro ao tentar realizar a soma
>>>

E já filtramos o erro, porém isso é muito vago, por que ocorreu o erro?

Para resolver isso, podemos criar exceções específicas para cada tipo de erro. O Python é bem gentil nessa parte e já te diz direto o tipo de erro. Voltando lá em cima no erro, qual o tipo de erro?

Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    N1 + N2
TypeError: unsupported operand type(s) for +: 'int' and 'str'


TypeError! Então aí já sabemos o tipo do erro e podemos criar uma exceção específica pra erros desse tipo:

>>> N1 = 25
>>> N2 = 'asd'
>>> try:
    N1 + N2
except TypeError:
    print('erro ao tentar realizar a soma, tipos de dados diferentes')


Executando:

erro ao tentar realizar a soma, tipos de dados diferentes
>>>

À primeira vista, parece ser a mesma coisa, usar except somente e except <tipo do erro>, mas para códigos maiores, onde existam possibilidades de tipos diferentes de erros, isso ajuda tanto o programador, quanto o usuário a terem uma ideia do que saiu errado.

Um exemplo genérico: dois erros comuns ao se trabalhar com urllib, um erro HTTP e um erro na URL:

>>> url.urlopen('http://www.sitenaoexiste.com')
Traceback (most recent call last):
  File "C:\Python34\lib\urllib\request.py", line 1174, in do_open
    h.request(req.get_method(), req.selector, req.data, headers)
  File "C:\Python34\lib\http\client.py", line 1090, in request
    self._send_request(method, url, body, headers)
  File "C:\Python34\lib\http\client.py", line 1128, in _send_request
    self.endheaders(body)
  File "C:\Python34\lib\http\client.py", line 1086, in endheaders
    self._send_output(message_body)
  File "C:\Python34\lib\http\client.py", line 924, in _send_output
    self.send(msg)
  File "C:\Python34\lib\http\client.py", line 859, in send
    self.connect()
  File "C:\Python34\lib\http\client.py", line 836, in connect
    self.timeout, self.source_address)
  File "C:\Python34\lib\socket.py", line 491, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
  File "C:\Python34\lib\socket.py", line 530, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 11004] getaddrinfo failed

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#61>", line 1, in <module>
    url.urlopen('http://www.sitenaoexiste.com')
  File "C:\Python34\lib\urllib\request.py", line 153, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Python34\lib\urllib\request.py", line 455, in open
    response = self._open(req, data)
  File "C:\Python34\lib\urllib\request.py", line 473, in _open
    '_open', req)
  File "C:\Python34\lib\urllib\request.py", line 433, in _call_chain
    result = func(*args)
  File "C:\Python34\lib\urllib\request.py", line 1202, in http_open
    return self.do_open(http.client.HTTPConnection, req)
  File "C:\Python34\lib\urllib\request.py", line 1176, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [Errno 11004] getaddrinfo failed>



>>> url.urlopen('http://www.webcheats.com.br')
Traceback (most recent call last):
  File "<pyshell#62>", line 1, in <module>
    url.urlopen('http://www.webcheats.com.br')
  File "C:\Python34\lib\urllib\request.py", line 153, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Python34\lib\urllib\request.py", line 461, in open
    response = meth(req, response)
  File "C:\Python34\lib\urllib\request.py", line 571, in http_response
    'http', request, response, code, msg, hdrs)
  File "C:\Python34\lib\urllib\request.py", line 499, in error
    return self._call_chain(*args)
  File "C:\Python34\lib\urllib\request.py", line 433, in _call_chain
    result = func(*args)
  File "C:\Python34\lib\urllib\request.py", line 579, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden

>>>

O primeiro erro é porque o site não existe, o segundo é porque o fórum bloqueia certas requisições, até onde eu vi, com base no user-agent, pois alterando o user-agent da minha requisição, consegui conectar (mas isso é assunto pra outra hora).

Se tentássemos usar o try, não saberíamos ao certo o que deu errado.

>>> try:
    url.urlopen('http://www.sitenaoexiste.com')
except:
    print('erro')

erro

>>> try:
    url.urlopen('http://www.webcheats.com.br')
except:
    print('erro')

erro
>>>

Já se tentarmos filtrar por tipo de erro:

>>> try:
    url.urlopen('http://www.sitenaoexiste.com')
except urllib.error.HTTPError:
    print('Erro HTTP')
except urllib.error.URLError:
    print('erro ao tentar abrir a URL')


erro ao tentar abrir a URL

>>> try:
    url.urlopen('http://www.webcheats.com.br')
except urllib.error.HTTPError:
    print('Erro HTTP')
except urllib.error.URLError:
    print('erro ao tentar abrir a URL')


Erro HTTP
>>>

Mas podemos dar ainda mais detalhes sobre o erro, de forma amigável, pegando o erro HTTP por exemplo, existem vários tipos: error 404, 403 etc, que são códigos que servem para dizer o que deu errado. Para quem quiser dar uma olhada nos códigos:
>>> try:
    url.urlopen('http://www.webcheats.com.br')
except urllib.error.HTTPError as errohttp:
    print('Erro HTTP, código do erro: {code}' .format(code = errohttp.code))
except urllib.error.URLError:
    print('erro ao tentar abrir a URL')


Erro HTTP, código do erro: 403
>>>

E é isso aí. :)

Fonte:
   

Páginas do artigo
   1. Introdução
Outros artigos deste autor

Sudo 1.8.12 - Parte II - Como sudo funciona

A camada de enlace de dados

Banda Larga é um direito de todos!

Atualizando o seu KDE sem dores de cabeça

Script de firewall e análise de log

Leitura recomendada

Configurando DOTNET Core e instalando VSCode no Linux

DesktopBSD - opção ao FreeBSD para desktops

Processos no Linux

Nova geração Linux

Gerenciamento de pacotes no Mandriva Linux

  
Comentários
[1] Comentário enviado por hrcerq em 27/02/2015 - 09:59h

Excelente artigo! Parabéns.

[2] Comentário enviado por malbrecht em 28/02/2015 - 08:48h

Muito bom artigo, Parabéns

[3] Comentário enviado por gilsonsilvati em 28/02/2015 - 17:07h

Show... Parabéns pelo tutorial!!! :-)

[4] Comentário enviado por bonilhasilvio em 07/03/2015 - 13:04h


Valeu, muito bom tutorial.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts