tl; dr / correção rápida
- Não decodifique / codifique willy nilly
- Não assuma que suas strings são codificadas em UTF-8
- Tente converter cadeias de caracteres para cadeias de caracteres Unicode o mais rápido possível no seu código
- Corrija seu código do idioma: Como resolver o UnicodeDecodeError no Python 3.6?
- Não fique tentado a usar
reload
hacks rápidos
Zen Unicode no Python 2.x - a versão longa
Sem ver a fonte, é difícil conhecer a causa raiz, então terei que falar em geral.
UnicodeDecodeError: 'ascii' codec can't decode byte
geralmente acontece quando você tenta converter um Python 2.x str
que contém não-ASCII em uma cadeia de caracteres Unicode sem especificar a codificação da cadeia de caracteres original.
Em resumo, as cadeias Unicode são um tipo totalmente separado de cadeia Python que não contém nenhuma codificação. Eles contêm apenas códigos de ponto Unicode e, portanto, podem conter qualquer ponto Unicode de todo o espectro. As strings contêm texto codificado, como UTF-8, UTF-16, ISO-8895-1, GBK, Big5 etc. As strings são decodificadas para Unicode e Unicodes são codificadas para strings . Arquivos e dados de texto são sempre transferidos em cadeias codificadas.
Os autores do módulo Markdown provavelmente usam unicode()
(onde a exceção é lançada) como uma porta de qualidade para o restante do código - ele converterá ASCII ou reorganizará as cadeias Unicodes existentes em uma nova cadeia Unicode. Os autores do Markdown não sabem a codificação da sequência de entrada, portanto, você decodificará as seqüências de caracteres em strings Unicode antes de passar para o Markdown.
As strings Unicode podem ser declaradas no seu código usando o u
prefixo das strings. Por exemplo
>>> my_u = u'my ünicôdé strįng'
>>> type(my_u)
<type 'unicode'>
As strings Unicode também podem vir de arquivos, bancos de dados e módulos de rede. Quando isso acontece, você não precisa se preocupar com a codificação.
Pegadinhas
A conversão de str
para Unicode pode ocorrer mesmo quando você não chama explicitamente unicode()
.
Os seguintes cenários causam UnicodeDecodeError
exceções:
# Explicit conversion without encoding
unicode('€')
# New style format string into Unicode string
# Python will try to convert value string to Unicode first
u"The currency is: {}".format('€')
# Old style format string into Unicode string
# Python will try to convert value string to Unicode first
u'The currency is: %s' % '€'
# Append string to Unicode
# Python will try to convert string to Unicode first
u'The currency is: ' + '€'
Exemplos
No diagrama a seguir, você pode ver como a palavra café
foi codificada na codificação "UTF-8" ou "Cp1252", dependendo do tipo de terminal. Nos dois exemplos, caf
são apenas ascii regulares. Em UTF-8, é
é codificado usando dois bytes. Em "Cp1252", é 0xE9 (que também é o valor do ponto Unicode (não é coincidência)). O correto decode()
é chamado e a conversão para um Python Unicode é bem-sucedida:
Neste diagrama, decode()
é chamado com ascii
(que é o mesmo que chamar unicode()
sem uma codificação fornecida). Como o ASCII não pode conter bytes maiores que 0x7F
, isso gerará uma UnicodeDecodeError
exceção:
O sanduíche Unicode
É uma boa prática formar um sanduíche Unicode no seu código, onde você decodifica todos os dados recebidos em cadeias Unicode, trabalha com Unicodes e depois codifica para str
s na saída. Isso evita que você se preocupe com a codificação de strings no meio do seu código.
Entrada / decodificação
Código fonte
Se você precisar inserir não-ASCII em seu código-fonte, basta criar cadeias Unicode prefixando-as com a u
. Por exemplo
u'Zürich'
Para permitir que o Python decodifique seu código-fonte, você precisará adicionar um cabeçalho de codificação para corresponder à codificação real do seu arquivo. Por exemplo, se seu arquivo foi codificado como 'UTF-8', você usaria:
# encoding: utf-8
Isso é necessário apenas quando você possui código não ASCII .
arquivos
Normalmente, dados não ASCII são recebidos de um arquivo. O io
módulo fornece um TextWrapper que decodifica seu arquivo rapidamente, usando um dado encoding
. Você deve usar a codificação correta para o arquivo - ele não pode ser facilmente adivinhado. Por exemplo, para um arquivo UTF-8:
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
my_unicode_string = my_file.read()
my_unicode_string
seria adequado para passar para Markdown. Se for UnicodeDecodeError
da read()
linha, você provavelmente já usou o valor de codificação errado.
Arquivos CSV
O módulo CSV do Python 2.7 não suporta caracteres não ASCII 😩. A ajuda está disponível, no entanto, com https://pypi.python.org/pypi/backports.csv .
Use-o como acima, mas passe o arquivo aberto para ele:
from backports import csv
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
for row in csv.reader(my_file):
yield row
Bases de dados
A maioria dos drivers de banco de dados Python pode retornar dados em Unicode, mas geralmente requer um pouco de configuração. Sempre use seqüências de caracteres Unicode para consultas SQL.
MySQL
Na cadeia de conexão, adicione:
charset='utf8',
use_unicode=True
Por exemplo
>>> db = MySQLdb.connect(host="localhost", user='root', passwd='passwd', db='sandbox', use_unicode=True, charset="utf8")
PostgreSQL
Adicionar:
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)
HTTP
As páginas da Web podem ser codificadas em praticamente qualquer codificação. O Content-type
cabeçalho deve conter um charset
campo para sugerir a codificação. O conteúdo pode ser decodificado manualmente contra esse valor. Como alternativa, Python-Requests retorna Unicodes em response.text
.
Manualmente
Se você precisar decodificar cadeias manualmente, pode simplesmente fazer my_string.decode(encoding)
, onde encoding
está a codificação apropriada. Os codecs suportados pelo Python 2.x são fornecidos aqui: Codificações padrão . Novamente, se você receber UnicodeDecodeError
, provavelmente terá a codificação errada.
A carne do sanduíche
Trabalhe com Unicodes como faria com strs normais.
Resultado
stdout / impressão
print
escreve através do fluxo stdout. O Python tenta configurar um codificador no stdout para que os Unicodes sejam codificados na codificação do console. Por exemplo, se um shell do Linux locale
for en_GB.UTF-8
, a saída será codificada para UTF-8
. No Windows, você estará limitado a uma página de código de 8 bits.
Um console configurado incorretamente, como código de idioma corrompido, pode levar a erros de impressão inesperados. PYTHONIOENCODING
A variável de ambiente pode forçar a codificação para stdout.
arquivos
Assim como a entrada, io.open
pode ser usado para converter transparentemente Unicodes em seqüências de bytes codificadas.
Base de dados
A mesma configuração para leitura permitirá que Unicodes sejam gravados diretamente.
Python 3
O Python 3 não é mais capaz de Unicode do que o Python 2.x, no entanto, é um pouco menos confuso sobre o assunto. Por exemplo, o regular str
agora é uma string Unicode e o antigo str
agora bytes
.
A codificação padrão é UTF-8, portanto, se você for .decode()
uma sequência de bytes sem fornecer uma codificação, o Python 3 usará a codificação UTF-8. Isso provavelmente corrige 50% dos problemas de Unicode das pessoas.
Além disso, open()
opera no modo de texto por padrão, então retorna decodificado str
(Unicode). A codificação é derivada do código de idioma, que tende a ser UTF-8 em sistemas Un * x ou uma página de código de 8 bits, como windows-1251, nas caixas do Windows.
Por que você não deve usar sys.setdefaultencoding('utf8')
É um hack desagradável (há uma razão para você usar reload
) que apenas mascara problemas e dificulta sua migração para o Python 3.x. Entenda o problema, corrija a causa raiz e aproveite o Unicode zen. Consulte Por que NÃO devemos usar sys.setdefaultencoding ("utf-8") em um script py? para mais detalhes