UnicodeDecodeError, byte de continuação inválido

257

Por que o item abaixo está falhando? e por que é bem-sucedido com o codec "latin-1"?

o = "a test of \xe9 char" #I want this to remain a string as this is what I am receiving
v = o.decode("utf-8")

resulta em:

 Traceback (most recent call last):  
 File "<stdin>", line 1, in <module>  
 File "C:\Python27\lib\encodings\utf_8.py",
 line 16, in decode
     return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError:
 'utf8' codec can't decode byte 0xe9 in position 10: invalid continuation byte
RuiDC
fonte

Respostas:

247

Em binário, 0xE9 parece 1110 1001. Se você ler sobre UTF-8 na Wikipedia , verá que esse byte deve ser seguido por dois do formulário 10xx xxxx. Então, por exemplo:

>>> b'\xe9\x80\x80'.decode('utf-8')
u'\u9000'

Mas essa é apenas a causa mecânica da exceção. Nesse caso, você tem uma string quase certamente codificada em latim 1. Você pode ver como UTF-8 e latin 1 parecem diferentes:

>>> u'\xe9'.encode('utf-8')
b'\xc3\xa9'
>>> u'\xe9'.encode('latin-1')
b'\xe9'

(Observe, estou usando uma combinação de representações Python 2 e 3. aqui. A entrada é válida em qualquer versão do Python, mas é improvável que o seu intérprete Python mostre as strings unicode e byte dessa maneira.)

Josh Lee
fonte
2
Obrigado (e ao outro que respondeu), eu estava sob a crença errada de que caracteres até 255 seriam convertidos diretamente.
RuiDC
Eu recebo um UnicodeEncodeError: 'ascii' codec can't encode characters in position 2-3: ordinal not in range(128)erro ao usar.encode(latin-1)
Shiva
234

Eu tive o mesmo erro quando tentei abrir um arquivo CSV pelo método pandas read_csv.

A solução foi alterar a codificação para 'latin-1':

pd.read_csv('ml-100k/u.item', sep='|', names=m_cols , encoding='latin-1')
Mazen Aly
fonte
1
Isso realmente resolve o problema? Basicamente, não basta dizer aos pandas para ignorar o byte, fazendo o downgrade para um estilo de codificação menos complexo?
Yu Chen
61

É UTF-8 inválido. Esse caractere é o caractere e-agudo no ISO-Latin1, e é por isso que ele obtém sucesso com esse conjunto de códigos.

Se você não conhece o conjunto de códigos em que está recebendo as strings, está com alguns problemas. Seria melhor se um único conjunto de códigos (com sorte UTF-8) fosse escolhido para o seu protocolo / aplicativo e você apenas rejeitaria aqueles que não decodificassem.

Se você não pode fazer isso, precisará de heurísticas.

Sami J. Lehtinen
fonte
2
E para heurísticas, consulte a biblioteca chardet.
mlissner
44

Como o UTF-8 é multibyte e não há char correspondente à sua combinação de \xe9 mais espaço a seguir.

Por que deveria ter sucesso em ambos utf-8 e latino-1?

Aqui, como a mesma frase deve estar no utf-8:

>>> o.decode('latin-1').encode("utf-8")
'a test of \xc3\xa9 char'
neurino
fonte
Latin-1 é uma família de codificação de byte único, portanto tudo deve ser definido em UTF-8. Mas por que em algum momento o Latin-1 vence?
Reihan_amn
11

Se esse erro surgir ao manipular um arquivo que acabou de ser aberto, verifique se você o abriu no 'rb'modo

Patrick Mutuku
fonte
2
Graças a esta resposta, foi possível evitar o erro de UnicodeDecodeError: o codec 'utf-8' não pode decodificar o byte 0xd7 na posição 2024079: byte de continuação inválido por soup = BeautifulSoup(open('webpage.html', 'rb'), 'html.parser')
Isaac Philip
6

Isso aconteceu comigo também, enquanto eu estava lendo um texto contendo hebraico .txt.

Eu cliquei: file -> save ase salvei este arquivo como uma UTF-8codificação

Alon Gouldman
fonte
5

O erro de código utf-8 geralmente ocorre quando o intervalo de valores numéricos excede de 0 a 127.

o motivo para gerar essa exceção é:

1) Se o ponto de código for <128, cada byte será igual ao valor do ponto de código. 2) Se o ponto de código for 128 ou superior, a cadeia Unicode não poderá ser representada nessa codificação. (Python gera uma exceção UnicodeEncodeError neste caso.)

Para superar isso, temos um conjunto de codificações, a mais utilizada é "Latin-1, também conhecida como ISO-8859-1"

Portanto, os pontos Unicode ISO-8859-1 de 0 a 255 são idênticos aos valores do Latin-1, portanto, a conversão para essa codificação requer simplesmente a conversão de pontos de código em valores de bytes; se um ponto de código maior que 255 for encontrado, a sequência não poderá ser codificada em Latin-1

quando essa exceção ocorre quando você está tentando carregar um conjunto de dados, tente usar este formato

df=pd.read_csv("top50.csv",encoding='ISO-8859-1')

Adicione a técnica de codificação no final da sintaxe, que aceita o carregamento do conjunto de dados.

surya
fonte
Olá e bem-vindo ao SO! Por favor edite sua resposta para garantir que ele melhora a outras respostas já presentes nesta questão.
hongsy 18/01
4

Use isto, se mostrar o erro de UTF-8

pd.read_csv('File_name.csv',encoding='latin-1')
Anshul Singh Suryan
fonte
-1

Nesse caso, tentei executar um arquivo .py que ativa um caminho / arquivo.sql.

Minha solução foi modificar a codificação do arquivo.sql para "UTF-8 sem BOM" e funciona!

Você pode fazer isso com o Notepad ++.

vou deixar uma parte do meu código.

/ Código /

con = psycopg2.connect (host = sys.argv [1], porta = sys.argv [2], dbname = sys.argv [3], usuário = sys.argv [4], senha = sys.argv [5] )

cursor = con.cursor () sqlfile = aberto (caminho, 'r')

Martin Taco
fonte