Estou tendo problemas para lidar com caracteres unicode do texto buscado em diferentes páginas da web (em sites diferentes). Estou usando o BeautifulSoup.
O problema é que o erro nem sempre é reproduzível; às vezes funciona com algumas páginas e, às vezes, vomita jogando a UnicodeEncodeError
. Eu tentei praticamente tudo o que consigo pensar e, no entanto, não encontrei nada que funcionasse de maneira consistente sem gerar algum tipo de erro relacionado ao Unicode.
Uma das seções do código que está causando problemas é mostrada abaixo:
agent_telno = agent.find('div', 'agent_contact_number')
agent_telno = '' if agent_telno is None else agent_telno.contents[0]
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
Aqui está um rastreamento de pilha produzido em ALGUMAS strings quando o snippet acima é executado:
Traceback (most recent call last):
File "foobar.py", line 792, in <module>
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 20: ordinal not in range(128)
Suspeito que isso ocorra porque algumas páginas (ou mais especificamente, páginas de alguns dos sites) podem ser codificadas, enquanto outras podem não ser codificadas. Todos os sites são baseados no Reino Unido e fornecem dados destinados ao consumo no Reino Unido - portanto, não há problemas relacionados à internalização ou ao tratamento de texto escrito em outro idioma que não seja o inglês.
Alguém tem alguma idéia de como resolver isso, para que eu possa consistentemente corrigir esse problema?
fonte
import os; import locale; os.environ["PYTHONIOENCODING"] = "utf-8"; myLocale=locale.setlocale(category=locale.LC_ALL, locale="en_GB.UTF-8"); ... print(myText.encode('utf-8', errors='ignore'))
.$ export PYTHONIOENCODING=utf8
Respostas:
Você precisa ler o HOWTO Unicode do Python . Este erro é o primeiro exemplo .
Basicamente, pare de usar
str
para converter de unicode em texto / bytes codificados.Em vez disso, use corretamente
.encode()
para codificar a sequência:ou trabalhe inteiramente em unicode.
fonte
print
minhas cordas utf-8, ele funciona muito bem. No entanto, quando canalizo a saída dos meus programas para um arquivo, ele lança aUnicodeEncodeError
. De fato, quando a saída é redirecionada (para um arquivo ou canal), acho quesys.stdout.encoding
éNone
! Pregar.encode('utf-8')
resolve o problema.PYTHONIOENCODING=utf-8
vez disso, ou seja, imprima seqüências Unicode e deixe o ambiente definir a codificação esperada..encode()
método para chamar.Este é um ponto de dor clássico do unicode python! Considere o seguinte:
Tudo bem até agora, mas se chamarmos str (a), vamos ver o que acontece:
Oh, mergulho, isso não vai fazer bem a ninguém! Para corrigir o erro, codifique os bytes explicitamente com .encode e diga ao python qual codec usar:
Voil \ u00E0!
O problema é que, quando você chama str (), python usa a codificação de caracteres padrão para tentar codificar os bytes que você forneceu, que no seu caso às vezes são representações de caracteres unicode. Para corrigir o problema, você precisa dizer ao python como lidar com a string fornecida usando .encode ('Whatever_unicode'). Na maioria das vezes, você deve ficar bem usando utf-8.
Para uma excelente exposição sobre esse assunto, consulte a conversa PyCon de Ned Batchelder aqui: http://nedbatchelder.com/text/unipain.html
fonte
None
valor.Encontrei um trabalho elegante para remover símbolos e continuar mantendo a string como a seguir:
É importante notar que o uso da opção ignorar é perigoso, pois elimina silenciosamente qualquer suporte a unicode (e internacionalização) do código que o utiliza, como pode ser visto aqui (converter unicode):
fonte
yourstring = yourstring.encode('utf-8', 'ignore').decode('utf-8')
os.path.join()
, é um hábito muito bom quando você começa a programar em várias plataformas. :)Bem, eu tentei de tudo, mas não ajudou. Depois de pesquisar no Google, percebi o seguinte e ajudou. python 2.7 está em uso.
fonte
if sys.version_info.major < 3:
Um problema sutil que causa falha na impressão é ter as variáveis de ambiente definidas incorretamente, por exemplo. aqui LC_ALL definido como "C". No Debian, eles desencorajam defini-lo: Debian wiki on Locale
fonte
env|grep -E '(LC|LANG)'
.mc
em "modo subshell" (Ctrl-O
) e também se esqueceu de que eu adicionei o seguinte apelido para bash:alias mc="LANG=en_EN.UTF-8 mc"
. Então, quando tentei executar scripts mal escritos, que dependemru_RU.UTF-8
internamente, eles simplesmente morrem. Tentei muitas coisas desse tópico antes de descobrir o problema real. :)Para mim, o que funcionou foi:
Espero que isso ajude alguém.
fonte
Na verdade, descobri que, na maioria dos meus casos, remover esses caracteres é muito mais simples:
fonte
O problema é que você está tentando imprimir um caractere unicode, mas seu terminal não o suporta.
Você pode tentar instalar o
language-pack-en
pacote para corrigir isso:que fornece atualizações de dados de tradução em inglês para todos os pacotes suportados (incluindo Python). Instale um pacote de idioma diferente, se necessário (dependendo dos caracteres que você está tentando imprimir).
Em algumas distribuições Linux, é necessário para garantir que as localidades padrão em inglês estejam configuradas corretamente (para que os caracteres unicode possam ser manipulados pelo shell / terminal). Às vezes, é mais fácil instalá-lo do que configurá-lo manualmente.
Então, ao escrever o código, use a codificação correta no seu código.
Por exemplo:
Se você ainda tiver um problema, verifique novamente a configuração do sistema, como:
Seu arquivo de localidade (
/etc/default/locale
), que deve ter, por exemplo,ou:
Valor de
LANG
/LC_CTYPE
no shell.Verifique qual localidade seu shell suporta:
Demonstrando o problema e a solução em uma nova VM.
Inicialize e provisione a VM (por exemplo, usando
vagrant
):Veja: caixas Ubuntu disponíveis . .
Impressão de caracteres unicode (como sinal de marca comercial
™
):Agora instalando
language-pack-en
:Agora o problema deve ser resolvido:
Caso contrário, tente o seguinte comando:
fonte
language-pack-en
a ver com Python ou com essa pergunta? AFAIK, pode fornecer traduções de idiomas para mensagens, mas não tem nada a ver com codificação/etc/locale.gen
para garantir que a localidade seja criada antes de usá-la?LANG
a partir/etc/default/locale
(como/etc/locale.gen
existem does't) e correulocale-gen
, mas não ajudou. Não sei o quelanguage-pack-en
exatamente faz, pois não encontrei muita documentação e listar o conteúdo dela não ajuda muito.LANG
/LC_CTYPE
/LC_ALL
(em vez dissoLANG=C.UTF-8
).Com casca:
Localize a localidade UTF-8 suportada pelo seguinte comando:
Exporte-o antes de executar o script, por exemplo:
ou manualmente como:
Teste-o imprimindo caracteres especiais, por exemplo
™
:Acima testado no Ubuntu.
fonte
Adicione a linha abaixo no início do seu script (ou como segunda linha):
Essa é a definição da codificação do código-fonte python. Mais informações em PEP 263 .
fonte
Aqui está uma retrospectiva de algumas outras respostas ditas "cop out". Há situações em que simplesmente jogar fora os caracteres / cordas problemáticos é uma boa solução, apesar dos protestos expressos aqui.
Testando:
Resultados:
Sugestão: você pode nomear essa função em
toAscii
vez disso? Essa é uma questão de preferência.Isso foi escrito para o Python 2. Para o Python 3, acredito que você queira usar em
bytes(obj,"ascii")
vez destr(obj)
. Ainda não testei isso, mas em algum momento revisarei a resposta.fonte
Eu sempre coloco o código abaixo nas duas primeiras linhas dos arquivos python:
fonte
Funções auxiliares simples encontradas aqui .
fonte
backslashreplace
manipulador de erro:u'\xa0'.encode('ascii', 'backslashreplace')
. Embora você deva evitar essa representação e configurar seu ambiente para aceitar caracteres não-ascii - é 2016!Basta adicionar a uma codificação variável ('utf-8')
fonte
Por favor, abra o terminal e dispare o comando abaixo:
fonte
Eu apenas usei o seguinte:
Verifique o que a documentação diz sobre isso:
Resolve para mim. Simples e fácil.
fonte
Abaixo solução funcionou para mim, apenas adicionou
(representando a string como unicode) antes da minha string.
fonte
Infelizmente isso funciona em Python 3, pelo menos ...
Python 3
Às vezes, o erro está nas variáveis do ambiente e envolve tanto
onde erros são ignorados na codificação.
fonte
Acabei de ter esse problema, e o Google me levou aqui, então, para adicionar às soluções gerais aqui, é isso que funcionou para mim:
Tive essa ideia depois de ler a apresentação de Ned .
Mas não pretendo entender completamente por que isso funciona. Portanto, se alguém puder editar esta resposta ou colocar um comentário para explicar, eu aprecio isso.
fonte
type
valor? antes e depois disso? Eu acho que por que isso funciona é que, fazendo umunic += value
que é o mesmo queunic = unic + value
você está adicionando uma string e um unicode, onde python assume unicode para o resultante,unic
ou seja, o tipo mais preciso (pense em quando você faz issoa = float(1) + int(1)
,a
torna-se um float) e depoisvalue = unic
apontavalue
para o novounic
objeto que passa a ser unicode.Ocorreu esse erro ao executar
manage.py migrate
no Django com equipamentos localizados.Nossa fonte continha a
# -*- coding: utf-8 -*-
declaração, o MySQL foi configurado corretamente para utf8 e o Ubuntu tinha o pacote de idiomas e os valores apropriados/etc/default/locale
.A questão era simplesmente que o contêiner do Django (usamos o docker) estava com falta do
LANG
env var.Configuração
LANG
paraen_US.UTF-8
e reiniciar o recipiente antes de migrações re-executar corrigiu o problema.fonte
Muitas respostas aqui (@agf e @Andbdrew, por exemplo) já abordaram os aspectos mais imediatos da questão do OP.
No entanto, acho que há um aspecto sutil, mas importante, que foi amplamente ignorado e que é muito importante para todos que gostam de mim aqui, enquanto tentam entender as codificações em Python: o gerenciamento de representação de caracteres em Python: Python 2 vs Python 3 é muito diferente . Eu sinto que um grande pedaço de confusão por aí tem a ver com pessoas lendo sobre codificações em Python sem estar ciente da versão.
Sugiro que qualquer pessoa interessada em entender a causa raiz do problema do OP comece lendo a introdução de Spolsky às representações de caracteres e Unicode e depois vá para Batchelder no Unicode no Python 2 e Python 3.
fonte
Tente evitar a conversão de variável em str (variável). Às vezes, pode causar o problema.
Dica simples para evitar:
O exemplo acima também resolverá o erro de codificação.
fonte
Se você tiver algo parecido
packet_data = "This is data"
, faça isso na próxima linha, logo após a inicializaçãopacket_data
:fonte
Atualização para o python 3.0 e posterior. Tente o seguinte no editor python:
Isso define a codificação de localidade padrão do sistema para o formato UTF-8.
Mais informações podem ser lidas aqui no PEP 538 - Coagindo a localidade C legada a uma localidade baseada em UTF-8 .
fonte
Eu tive esse problema tentando gerar caracteres Unicode
stdout
, mas comsys.stdout.write
, em vez de imprimir (para que eu também pudesse suportar a saída para um arquivo diferente).Na documentação do BeautifulSoup , resolvi isso com a biblioteca de codecs:
fonte
Esse problema geralmente ocorre quando um projeto django é implementado usando o Apache. Como o Apache define a variável de ambiente LANG = C em / etc / sysconfig / httpd. Basta abrir o arquivo e comentar (ou alterar para o seu flavior) essa configuração. Ou use a opção lang do comando WSGIDaemonProcess; nesse caso, você poderá definir diferentes variáveis de ambiente LANG para diferentes virtualhosts.
fonte
A solução recomendada não funcionou para mim, e eu poderia viver com o dumping de todos os caracteres não ascii, portanto
o que me deixou com algo despido que não gera erros.
fonte
Isso funcionará:
Resultado:
fonte