Written by: Helio Loureiro
Category: Python
Hits: 8092

Não é de hoje que me deparo com esses erros de unicode em python.

Em algumas funções que uso, principalmente as que lêem de timeline de redes sociais, tenho problemas com caracteres.  Dessa vez eu estava fazendo um programa que lê a timeline da rede social da empresa, que é baseada num produto lixo da Microsoft, o ShamePoint, digo, SharePoint, que publica a API de mensagens no formato RSS.  A função é pra gerar um gráfico de mensagens a cada 5 minutos para verificar o andamento da rede social (que passou do momento de hype).  Então como o ShamePoint é limitado em suas funções, resolvi fazer um "tracking" de posts através de uma função com um hash MD5 da mensagem postada.  

A idéia não é muito complexa, mas eis que fazendo o hash eu achei um:


helio@shibboleet:pynet$ ./mynet_tag_posts.py
Getting posts
Reading output and rss
Traceback (most recent call last):
  File "./mynet_tag_posts.py", line 106, in 
    main()
  File "./mynet_tag_posts.py", line 103, in main
    RSS = RSS_parser(XML)
  File "./mynet_tag_posts.py", line 60, in RSS_parser
    key = md5sum(rss.summary_detail.value)
  File "./mynet_tag_posts.py", line 19, in md5sum
    m.update(msg)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xc5' in position 96: ordinal not in range(128)

E a função de hash MD5, a md5sum(), é super simples:


def md5sum(msg):
  m = hashlib.md5()
  m.update(msg)
  return m.hexdigest()

Só que mensagens com caracteres não ASCII, como em português ou suéco, simplesmente matam o processamento do MD5.

Em outros scripts eu contornei isso fazendo uma análise por caractere e substituindo todo aquele que tivesse valor maior que 128 por seu semelhante não acentuado na tabela ASCII.   Trabalho tosco, mas funcional.

Dessa vez resolvi procurar como corrigir isso.  E pra sempre.  Procurei na documentação do python sobre tratamento de unicode.

E não é que achei a solução do jeito mais simples e pythonista possível?  Basta forçar um atributo de formato de caractere no texto, como texto.encode(formato).  No caso, mudei a função para essa abaixo, usando formato de caracteres "utf-8":


def md5sum(msg):
  m = hashlib.md5()
  msg = msg.encode('utf-8')
  m.update(msg)
  return m.hexdigest()

E o problema foi resolvido.  Sem mais chororo de formatos iso-8859-1 e utf-8.