Como contornar o erro do Python ' UnicodeEncodeError: ' ascii ' codec não pode codificar caracteres … ' ao usar um script Python na linha de comando

Melhor resposta

Desculpe, não há uma resposta simples de uma linha para esse problema.

Imagine que uma string entra em um programa python por meio de uma operação de E / S (lida do terminal, ou do arquivo, ou da rede), percorre o programa sendo copiado de um lugar para outro, e, finalmente, obtém a saída por meio de uma operação de E / S. Em qualquer etapa do caminho, se você atribuir um unicode a um str, verá o temido erro ascii codec can"t encode.... Infelizmente, não há maneira fácil de consertá-lo a não ser ir através do seu código corrigindo todos os pontos.

Por exemplo, considere:

f\_in = open("filein.txt")

line = f\_in.read()

out\_msg = "The input line was: {line}".format(line=line)

f\_out = open("fileout.txt")

A menos que você saiba qual codificação foi usada ao armazenar filein.txt, você terá um comportamento bizarro e alguns caracteres em seu line parecerão lixo. (Observação: você ganhou ” não obtenha o erro ascii codec can"t encode..., mas os resultados serão ruins mesmo assim.) Portanto, você precisa usar algo como: f\_in = codecs.open("filein.txt", "rb", "utf-8") e esperar desesperadamente que quem armazenou filein.txt o armazenou em utf-8 e não em uma das outras codificações UTF. (Nota: utf-8 é compatível com ascii para cima, então um arquivo que foi armazenado usando ascii regular abrirá bem usando a codificação utf-8).

A esta altura, você obviamente deve ter percebido isso, a menos que abra fileout.txt usando uma codificação Unicode apropriada, você novamente terá problemas e obterá o erro ascii codec can"t encode... (se seu out\_msg contiver qualquer caractere Unicode). Portanto, você precisa fazer codecs.open("fileout.txt", "wb", "utf-8"). (Observe novamente: usar uma codificação utf-8 para armazenar ASCII regular não é um problema, uma vez que é compatível com versões anteriores, portanto, se seu texto não contiver caracteres Unicode não ASCII , o arquivo codificado em utf-8 é idêntico a um arquivo ASCII regular.)

O que me surpreendeu foi que fazer essas duas coisas não é bom o suficiente. Considere este código atualizado:

f\_in = codecs.open("filein.txt", "rb", "utf-8")

line = f\_in.read()

out\_msg = "The input line was: {line}".format(line=line)

f\_out = codecs.open("fileout.txt", "wb", "utf-8")

Isso ainda pode dar a você o mesmo erro temido no terceiro linha. É isso mesmo, o problema é que "The input line was: {line}".format(xxx)" é um str e se line contém quaisquer caracteres Unicode (quero dizer, caracteres que não podem ser codificados em ascii), você está com problemas.

A solução para isso é:

out\_msg = u"The input line was: {line}".format(line=line)

(Sim, esta linha é diferente da linha 3 no exemplo de código. Você só precisa olhar com atenção.)

Então aí está. Precisa ir até cada linha de seu código e encontre lugares onde unicode está sendo atribuído a str (ou está sendo enviado a um método que espera um str) e fixe o destino para ser unicode em vez de str.

Para entender unicode em melhor python, dê uma olhada em: http://farmdev.com/thoughts/23/what-i-thought-i-knew-about-unicode-in-python-amounted-to-nothing/

Para entender Unicode em geral (e eu altamente recomendo que você faça isso) leia Joel Spolsky “s” O Mínimo Absoluto Todo Desenvolvedor de Software Absolutamente, Positivamente Deve Saber Sobre Unicode e Conjuntos de Caracteres (Não Desculpas!) “: http://www.joelonsoftware.com/articles/Unicode.html

E já que você está falando nisso, também pode ler: Qual é a melhor fonte para aprender sobre as práticas recomendadas de Unicode em python?

Quick “n Dirty Hack: Se você apenas deseja obter alguma saída impressa em ascii aproximado, você pode fazer:

import unicodedata

line = unicodedata.normalize("NFKD", line).encode("ascii","ignore")

Isso irá substituir todos os caracteres não ascii pelo equivalente ascii mais próximo ou apenas ignorar o caractere se nada for apropriado . É bom o suficiente para muitos propósitos …

Resposta

Você deve converter suas strings Unicode (que são feitas de caracteres, uma unidade desacoplada do tamanho da memória) em bytes usando a codificação adequada antes de fazer qualquer I / O com ele.

Por padrão, Python tenta codificar sua string Unicode usando a codificação ASCII ao gravar no stdout (ou seja, usando imprimir ), mas essa codificação não pode “representar todos os caracteres Unicode, e é por isso que você está recebendo esse erro:” o codec “ascii” não pode “codificar caracteres”. Muito explícito.

Você deve escolher uma codificação adequada e codificar sua string Unicode usando ela. Por exemplo, UTF-8 é uma codificação eficiente que pode lidar com todos os caracteres Unicode. Supondo que foo seja uma string Unicode, você poderia (e deveria) fazer: print foo.encode (“utf -8 “) em vez de apenas imprimir foo . Apenas certifique-se de que seu terminal ou qualquer outra coisa entenda a codificação que você escolher.Novamente: UTF-8 é a codificação mais avançada que existe para cenários como este, você provavelmente vai querer usá-la, a menos que tenha necessidades muito específicas.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *