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.