Converter uma string Unicode em uma string em Python (contendo símbolos extras)

504

Como você converte uma string Unicode (contendo caracteres extras, como $ $ etc.) em uma string Python?

williamtroup
fonte
2
Precisamos saber qual versão do Python você está usando e o que você está chamando de uma string Unicode. Faça o seguinte em um curto unicode_string que inclui os símbolos monetários que estão causando o incômodo: Python 2.x: print type(unicode_string), repr(unicode_string)Python 3.x: print type(unicode_string), ascii(unicode_string)edite sua pergunta e copie / cole os resultados da declaração de impressão acima. NÃO redigite os resultados. Também olhar para cima perto do topo de sua HTML e veja se você pode encontrar algo parecido com isto: <meta http-equiv = "Content-Type" content = "text / html; charset = iso-8859
John Machin
3
Duvido que você obtenha unicode de uma solicitação da web. Você provavelmente obtém Unicode codificado em UTF-8.
28
@lutz: como exatamente "Unicode codificado em UTF-8" não é unicode?
jalf
2
Você realmente deve esclarecer o que quer dizer com string unicode e python (dar exemplos concretos seria o melhor, eu acho), pois fica claro nos comentários que existem diferentes interpretações da sua pergunta. Eu me pergunto por que você não fez isso, apesar de já fazer mais de 3,5 anos desde que você fez essa pergunta.
Piotr Dobrogost
6
@ jalf: se estiver codificado ; não é mais Unicode, por exemplo,unicode_string = u"I'm unicode string"; bytestring = unicode_string.encode('utf-8'); unicode_again = bytestring.decode('utf-8')
jfs 21/12/2013

Respostas:

573

Vejo unicodedata.normalize

title = u"Klüft skräms inför på fédéral électoral große"
import unicodedata
unicodedata.normalize('NFKD', title).encode('ascii', 'ignore')
'Kluft skrams infor pa federal electoral groe'
Sorantis
fonte
24
+1 responde à pergunta, tal como formulada, @ problema de williamtroup de não ser capaz de salvar unicode para um sons de arquivo como uma questão totalmente diferente digno de uma questão separada
Mark Roddy
5
@ John - essa resposta é anterior ao esclarecimento do OP.
Dominic Rodger
10
@ Mark Roddy: Sua pergunta, como está escrita, é como converter uma "string Unicode" (o que ele quer dizer com isso) contendo alguns símbolos monetários em uma "string Python" (o que seja ...) e você acha que um remove-some-diacritics delete-other-non-ascii characters kludge responde sua pergunta ???
John Machin
13
@JohnMachin Isso responde à pergunta palavra por palavra: A única maneira de converter uma unicodestring em a stré soltar ou converter os caracteres que não podem ser representados em ASCII. Então, um de mim.
Izkata
4
@lzkata: não, não é. type(title) == unicode and type(title.encode('utf-8')) == str. Não há necessidade de corromper a entrada, para obter uma cadeia de bytes que pode ser salva em um arquivo.
JFS
319

Você pode usar a codificação para ASCII se não precisar converter os caracteres não ASCII:

>>> a=u"aaaàçççñññ"
>>> type(a)
<type 'unicode'>
>>> a.encode('ascii','ignore')
'aaa'
>>> a.encode('ascii','replace')
'aaa???????'
>>>
Ferran
fonte
4
Resposta incrível. Exatamente o que eu precisava. Além disso, grande apresentação para mostrar o efeito da ignorevsreplace
Jonny Brooks
ou a.encode('ascii', 'xmlcharrefreplace')'aaa&#224;&#231;&#231;&#231;&#241;&#241;&#241;'.
22819 Bob Stein
type(a)está strno Python 3.6.8 e não possui nenhum encode()método.
Ali Tou
138
>>> text=u'abcd'
>>> str(text)
'abcd'

Se a sequência contiver apenas caracteres ascii.

igco
fonte
18
Isso funcionaria apenas no Windows. E quebrará se houver símbolos não-ascii.
Vanuan
6
Isso é interrompido se o conteúdo da string for realmente unicode, não apenas caracteres ascii em uma string unicode. Não faça isso, você receberá exceções aleatórias UnicodeEncodeError em todo o lugar.
Doug
11
Essa resposta me ajudou. Se você sabe que sua string é ascii e precisa convertê-la novamente em uma string não unicode, isso é muito útil.
VedTopkar
113

Se você possui uma seqüência de caracteres Unicode e deseja gravá-la em um arquivo ou outro formulário serializado, primeiro deve codificá- la em uma representação específica que possa ser armazenada. Existem várias codificações Unicode comuns, como UTF-16 (usa dois bytes para a maioria dos caracteres Unicode) ou UTF-8 (1-4 bytes / ponto de código, dependendo do caractere), etc. Para converter essa sequência em uma codificação específica, você deve pode usar:

>>> s= u'£10'
>>> s.encode('utf8')
'\xc2\x9c10'
>>> s.encode('utf16')
'\xff\xfe\x9c\x001\x000\x00'

Essa sequência bruta de bytes pode ser gravada em um arquivo. No entanto, observe que, ao lê-lo novamente, você deve saber em que codificação está e decodificá-lo usando a mesma codificação.

Ao gravar em arquivos, você pode se livrar desse processo manual de codificação / decodificação usando o módulo de codecs . Portanto, para abrir um arquivo que codifica todas as seqüências Unicode no UTF-8 , use:

import codecs
f = codecs.open('path/to/file.txt','w','utf8')
f.write(my_unicode_string)  # Stored on disk as UTF-8

Observe que qualquer outra coisa que esteja usando esses arquivos deve entender em que codificação está o arquivo se eles quiserem lê-los. Se você é o único a fazer a leitura / gravação, isso não é um problema; caso contrário, certifique-se de escrever de uma forma compreensível por qualquer outra pessoa que use os arquivos.

No Python 3, essa forma de acesso ao arquivo é o padrão, e a openfunção interna aceita um parâmetro de codificação e sempre traduz de / para strings Unicode (o objeto de string padrão no Python 3) para arquivos abertos no modo de texto.

Brian
fonte
58

Aqui está um exemplo:

>>> u = u'€€€'
>>> s = u.encode('utf8')
>>> s
'\xe2\x82\xac\xe2\x82\xac\xe2\x82\xac'
Bastien Léonard
fonte
1
Alguém pode explicar por que, quando codifico o símbolo do Euro utf8como mostrado aqui, o resultado é apenas pontos de interrogação? Aqui está uma imagem do meu Python, versão 2.7.13. (I pode codificar outros objetos unicode como u"Klüft", mas não os Euros?)
The Red Pea
5

Bem, se você estiver disposto / pronto para mudar para o Python 3 (o que pode não ser devido à incompatibilidade reversa com algum código do Python 2), você não precisa fazer nenhuma conversão; todo o texto no Python 3 é representado por strings Unicode, o que também significa que não há mais uso da u'<text>'sintaxe. Você também tem o que são, na verdade, cadeias de bytes, que são usadas para representar dados (que podem ser uma cadeia codificada).

http://docs.python.org/3.1/whatsnew/3.0.html#text-vs-data-instead-of-unicode-vs-8-bit

(Obviamente, se você estiver usando o Python 3, provavelmente o problema está relacionado à maneira como você está tentando salvar o texto em um arquivo.)

JAB
fonte
2
No Python 3, as strings são Unicode. Eles nunca são codificados. Eu encontrei o seguinte texto útil: joelonsoftware.com/articles/Unicode.html
Ele quer salvá-lo em um arquivo; como sua resposta ajuda nisso?
John Machin
@lutz: Certo, eu tinha esquecido que o Unicode é um mapa de caracteres e não uma codificação. @ John: Não há informações suficientes no momento para saber qual é o problema de salvá-las. Ele está recebendo um erro? Ele não está recebendo nenhum erro, mas ao abrir o arquivo externamente, ele recebe mojibake? Sem essa informação, existem muitas soluções possíveis que poderiam ser fornecidas.
JAB
@ Cat: Não há informações no momento para saber o que ele tem, muito menos qual é o seu problema de economia. Pedi-lhe para fornecer alguns fatos - veja minha resposta.
John Machin
5

Aqui está um código de exemplo

import unicodedata    
raw_text = u"here $%6757 dfgdfg"
convert_text = unicodedata.normalize('NFKD', raw_text).encode('ascii','ignore')
Gihan Chathuranga
fonte
como esta resposta é diferente da resposta aceita?
sgauri
3

O arquivo contém uma seqüência de caracteres com escape em unicode

\"message\": \"\\u0410\\u0432\\u0442\\u043e\\u0437\\u0430\\u0446\\u0438\\u044f .....\",

para mim

 f = open("56ad62-json.log", encoding="utf-8")
 qq=f.readline() 

 print(qq)                          
 {"log":\"message\": \"\\u0410\\u0432\\u0442\\u043e\\u0440\\u0438\\u0437\\u0430\\u0446\\u0438\\u044f \\u043f\\u043e\\u043b\\u044c\\u0437\\u043e\\u0432\\u0430\\u0442\\u0435\\u043b\\u044f\"}

(qq.encode().decode("unicode-escape").encode().decode("unicode-escape")) 
# '{"log":"message": "Авторизация пользователя"}\n'
madjardi
fonte
2
funcionou mesmo se eu só usar:result.encode().decode('unicode-escape')
Ammad Khalid 15/01
0

Nenhuma resposta funcionou para o meu caso, onde eu tinha uma variável de string contendo caracteres unicode e nenhuma codificação-decodificação explicada aqui fez o trabalho.

Se eu fizer em um terminal

echo "no me llama mucho la atenci\u00f3n"

ou

python3
>>> print("no me llama mucho la atenci\u00f3n")

A saída está correta:

output: no me llama mucho la atención

Mas trabalhar com scripts que carregam essa variável de sequência não funcionou.

Isto é o que funcionou no meu caso , no caso de ajudar alguém:

string_to_convert = "no me llama mucho la atenci\u00f3n"
print(json.dumps(json.loads(r'"%s"' % string_to_convert), ensure_ascii=False))
output: no me llama mucho la atención
pctripsesp
fonte
você precisa importar json
pctripsesp 5/11/19