“For line in…” resulta em UnicodeDecodeError: o codec 'utf-8' não pode decodificar byte

214

Aqui está o meu código,

for line in open('u.item'):
#read each line

sempre que executo esse código, ocorre o seguinte erro:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 2892: invalid continuation byte

Eu tentei resolver isso e adicionar um parâmetro extra em open (), o código parece;

for line in open('u.item', encoding='utf-8'):
#read each line

Mas, novamente, dá o mesmo erro. o que devo fazer então! Por favor ajude.

SujitS
fonte
3
Dados mal codificados, eu diria.
Andreas Jung
9
Ou simplesmente não dados UTF-8.
precisa
Possível duplicata do Python 3 UnicodeDecodeError - Como depurar UnicodeDecodeError?
Tripleee 19/01/19
Tivemos esse erro com o msgpack ao usar o python 3 em vez do python 2.7. Para nós, o curso de ação foi trabalhar com o python 2.7.
Jesse W. Collins

Respostas:

402

Conforme sugerido por Mark Ransom, encontrei a codificação correta para esse problema. A codificação era "ISO-8859-1", portanto, a substituição open("u.item", encoding="utf-8")por open('u.item', encoding = "ISO-8859-1")resolverá o problema.

SujitS
fonte
8
Explícito é melhor que implícito (PEP 20).
Ioannis Filippidis 01/07/19
6
O truque é que ISO-8859-1 ou Latin_1 são conjuntos de caracteres de 8 bits, portanto, todo lixo tem um valor válido. Talvez não seja utilizável, mas se você quiser ignorar!
precisa saber é o seguinte
1
Eu tive o mesmo problema UnicodeDecodeError: o codec 'utf-8' não pode decodificar o byte 0xd0 na posição 32: byte de continuação inválido. Eu usei o python 3.6.5 para instalar o aws cli. E quando eu tentei o aws --version, ele falhou com este erro. Então eu tive que editar /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/configparser.py e alterei o código para a seguinte leitura def (self, nomes de arquivos, codificação = "ISO-8859-1" ):
Евгений Коптюбенко
3
Existe uma maneira automática de detectar codificação?
OrangeSherbet
5
@OrangeSherbet I implementado detecção utilizando chardet. Aqui está o one-liner (depois import chardet): chardet.detect(open(in_file, 'rb').read())['encoding']. Verifique esta resposta para obter detalhes: stackoverflow.com/a/3323810/615422
VertigoRay 20/03/19
51

Também funcionou para mim, a ISO 8859-1 vai economizar muito, hahaha, principalmente se estiver usando APIs de reconhecimento de fala

Exemplo:

file = open('../Resources/' + filename, 'r', encoding="ISO-8859-1");
Ryoji Kuwae Neto
fonte
4
Você pode estar certo de que o OP está lendo ISO 8859-1, como pode ser deduzido do 0xe9 (é) na mensagem de erro, mas você deve explicar por que sua solução funciona. A referência às APIs de reconhecimento de fala não ajuda.
RolfBly
5
O que há com o ponto e vírgula?
Perna direita
29

Na verdade, seu arquivo não contém dados codificados utf-8, contém algumas outras codificações. Descubra o que é essa codificação e use-a na openchamada.

No Windows-1252, por exemplo, a codificação 0xe9seria o caractere é.

Mark Ransom
fonte
4
Então, como posso descobrir qual é a codificação! Estou usando o linux
SujitS
4
Não existe uma maneira de fazer isso que sempre funcione, mas veja a resposta para esta pergunta: stackoverflow.com/questions/436220/…
RemcoGerlich
20

Tente ler isto usando pandas

pd.read_csv('u.item', sep='|', names=m_cols , encoding='latin-1')
Shashank
fonte
Não sei por que você está sugerindo pandas. A solução está definindo a codificação correta, com a qual você se deparou aqui.
Alastair McCormack
12

Se você estiver usando Python 2o seguinte, a solução:

import io
for line in io.open("u.item", encoding="ISO-8859-1"):
    # do something

Como o encodingparâmetro não funciona open(), você receberá o seguinte erro:

TypeError: 'encoding' é um argumento de palavra-chave inválido para esta função
Jeril
fonte
1
Mas esta é a versão 3
SujitS 03/03
1
Sim, eu sei. Eu pensei que poderia ser útil para as pessoas que utilizamPython 2
Jeril
Trabalhou para mim também em Python3
fenkerbb
2
Caso você queira algo mais fácil de lembrar, 'ISO-8859-1'também é conhecido como 'latin-1'ou 'latin1'.
Max Candocia
9

Você pode resolver o problema com:

for line in open(your_file_path, 'rb'):

'rb' está lendo o arquivo no modo binário. Leia mais aqui . Espero que isso ajude!

Ozcar Nguyen
fonte
6

Isso funciona:

open('filename', encoding='latin-1')

ou:

open('filename',encoding="IS0-8859-1")
Ayesha Siddiqa
fonte
2

Se alguém procurá-los, este é um exemplo para converter um arquivo CSV no Python 3:

try:
    inputReader = csv.reader(open(argv[1], encoding='ISO-8859-1'), delimiter=',',quotechar='"')
except IOError:
    pass
user6832484
fonte
2

Às vezes, quando open(filepath)em que na filepathverdade não é um arquivo, o mesmo erro ocorre; primeiro, verifique se o arquivo que você está tentando abrir existe:

import os
assert os.path.isfile(filepath)

espero que isso ajude.

xtluo
fonte
1

você pode tentar desta maneira:

open('u.item', encoding='utf8', errors='ignore')
FaridLU
fonte
Isso não fornece uma resposta para a pergunta. Para criticar ou solicitar esclarecimentos a um autor, deixe um comentário abaixo da postagem. - Da avaliação
MartenCatcher