Convierta una cadena Unicode en una cadena en Python (que contiene símbolos adicionales)

504

¿Cómo se convierte una cadena Unicode (que contiene caracteres adicionales como £ $, etc.) en una cadena Python?

williamtroup
fuente
2
Necesitamos saber qué versión de Python está utilizando y qué es lo que está llamando a una cadena Unicode. Haga lo siguiente en una cadena_unicode corta que incluye los símbolos de moneda que causan la molestia: Python 2.x: print type(unicode_string), repr(unicode_string)Python 3.x: print type(unicode_string), ascii(unicode_string)Luego edite su pregunta y copie / pegue los resultados de la declaración de impresión anterior. NO vuelva a escribir los resultados. También busque cerca de la parte superior de su HTML y vea si puede encontrar algo como esto: <meta http-equiv = "Content-Type" content = "text / html; charset = iso-8859
John Machin el
3
Dudo que obtenga unicode de una solicitud web. Probablemente obtengas UTF-8 codificado Unicode.
28
@lutz: ¿cómo es exactamente que "Unicode codificado en UTF-8" no es unicode?
jalf
2
Realmente deberías aclarar lo que quieres decir con cadena Unicode y cadena Python (supongo que dar ejemplos concretos sería lo mejor), ya que está claro por los comentarios que hay diferentes interpretaciones de tu pregunta. Me pregunto por qué no has hecho esto, aunque han pasado más de 3,5 años desde que hiciste esta pregunta.
Piotr Dobrogost
66
@jalf: si está codificado ; ya no es Unicode, por ejemplo,unicode_string = u"I'm unicode string"; bytestring = unicode_string.encode('utf-8'); unicode_again = bytestring.decode('utf-8')
jfs

Respuestas:

573

Ver 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
fuente
24
+1 responde a la pregunta tal como está redactado, el problema de @ williamtroup de no ser capaz de salvar a Unicode en un archivo de sonidos como una cuestión totalmente diferente digno de una pregunta separada
Marcos Roddy
55
@John: esa respuesta es anterior a la aclaración del OP.
Dominic Rodger el
10
@ Mark Roddy: Su pregunta tal como está escrita es cómo convertir una "cadena Unicode" (lo que quiera que quiera decir con eso) que contenga algunos símbolos de moneda en una "cadena Python" (lo que sea ...) y usted piensa que quitar un poco de diacríticos eliminar-otros-no-ascii personajes kludge responde a su pregunta ???
John Machin
13
@JohnMachin Esto responde la pregunta palabra por palabra: la única forma de convertir una unicodecadena en a stres soltar o convertir los caracteres que no se pueden representar en ASCII. Entonces +1 de mi parte.
Izkata
44
@lzkata: no, no lo es. type(title) == unicode and type(title.encode('utf-8')) == str. No es necesario corromper la entrada para obtener una cadena de bytes que se pueda guardar en un archivo.
jfs
319

Puede usar la codificación a ASCII si no necesita traducir los caracteres que no son ASCII:

>>> a=u"aaaàçççñññ"
>>> type(a)
<type 'unicode'>
>>> a.encode('ascii','ignore')
'aaa'
>>> a.encode('ascii','replace')
'aaa???????'
>>>
Ferran
fuente
44
Impresionante respuesta. Exactamente lo que necesitaba. Además, gran presentación para mostrar el efecto de ignorevsreplace
Jonny Brooks
o a.encode('ascii', 'xmlcharrefreplace')da 'aaa&#224;&#231;&#231;&#231;&#241;&#241;&#241;'.
Bob Stein
type(a)está stren Python 3.6.8 y no tiene ningún encode()método.
Ali Tou
138
>>> text=u'abcd'
>>> str(text)
'abcd'

Si la cadena solo contiene caracteres ascii.

igco
fuente
18
Esto solo funcionaría en Windows. Y se romperá si hay símbolos que no sean ascii.
Vanuan
66
Esto se rompe si el contenido de la cadena es realmente unicode, no solo caracteres ascii en una cadena unicode. No hagas esto, obtendrás excepciones UnicodeEncodeError aleatorias por todo el lugar.
Doug
11
Esta respuesta me ayudó. Si sabe que su cadena es ascii y necesita volver a convertirla en una cadena no unicode, esto es muy útil.
VedTopkar
113

Si tiene una cadena Unicode y desea escribirla en un archivo u otra forma serializada, primero debe codificarla en una representación particular que pueda almacenarse. Hay varias codificaciones Unicode comunes, como UTF-16 (usa dos bytes para la mayoría de los caracteres Unicode) o UTF-8 (1-4 bytes / punto de código según el carácter), etc. Para convertir esa cadena en una codificación particular, usted puedo usar:

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

Esta cadena de bytes sin procesar se puede escribir en un archivo. Sin embargo, tenga en cuenta que al volver a leerlo, debe saber en qué codificación se encuentra y decodificarlo utilizando esa misma codificación.

Al escribir en archivos, puede deshacerse de este proceso manual de codificación / decodificación utilizando el módulo de códecs . Entonces, para abrir un archivo que codifica todas las cadenas Unicode en 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

Tenga en cuenta que cualquier otra cosa que use estos archivos debe comprender en qué codificación está el archivo si desea leerlos. Si usted es el único que hace la lectura / escritura, esto no es un problema, de lo contrario, asegúrese de escribir de forma comprensible para cualquier otra persona que use los archivos.

En Python 3, esta forma de acceso a archivos es la predeterminada, y la openfunción incorporada tomará un parámetro de codificación y siempre se traducirá a / desde cadenas Unicode (el objeto de cadena predeterminado en Python 3) para los archivos abiertos en modo de texto.

Brian
fuente
58

Aquí hay un ejemplo:

>>> u = u'€€€'
>>> s = u.encode('utf8')
>>> s
'\xe2\x82\xac\xe2\x82\xac\xe2\x82\xac'
Bastien Léonard
fuente
1
¿Alguien puede explicar por qué, cuando codifico el símbolo del Euro utf8como se muestra aquí, el resultado son solo signos de interrogación? Aquí hay una imagen de mi Python, versión 2.7.13. (Puedo codificar otros objetos Unicode como u"Klüft", ¿pero no los Euros?)
The Red Pea
5

Bueno, si está dispuesto / listo para cambiar a Python 3 (lo que puede no ser debido a la incompatibilidad hacia atrás con algún código de Python 2), no tiene que realizar ninguna conversión; todo el texto en Python 3 se representa con cadenas Unicode, lo que también significa que no hay más uso de la u'<text>'sintaxis. También tiene lo que son, en efecto, cadenas de bytes, que se utilizan para representar datos (que pueden ser una cadena codificada).

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

(Por supuesto, si actualmente está usando Python 3, entonces el problema probablemente esté relacionado con la forma en que intenta guardar el texto en un archivo).

PINCHAZO
fuente
2
En Python 3, las cadenas son cadenas Unicode. Nunca están codificados. El siguiente texto me pareció útil: joelonsoftware.com/articles/Unicode.html
Quiere guardarlo en un archivo; ¿Cómo ayuda tu respuesta con eso?
John Machin el
@lutz: Correcto, había olvidado que Unicode es un mapa de caracteres en lugar de una codificación. @ John: No hay suficiente información en este momento para saber cuál es el problema al guardarlo. ¿Está recibiendo un error? ¿No está recibiendo ningún error, pero al abrir el archivo externamente obtiene mojibake? Sin esa información, hay demasiadas soluciones posibles que podrían proporcionarse.
JAB
@ Cat: No hay ninguna información en este momento para saber lo que tiene, y mucho menos cuál es su problema de ahorro. Le he pedido que proporcione algunos datos; vea mi respuesta.
John Machin el
5

Aquí hay un código de ejemplo

import unicodedata    
raw_text = u"here $%6757 dfgdfg"
convert_text = unicodedata.normalize('NFKD', raw_text).encode('ascii','ignore')
Gihan Chathuranga
fuente
¿Cómo esta respuesta es diferente de la respuesta aceptada?
sgauri
3

el archivo contiene una cadena unicode-esaped

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

para mi

 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
fuente
2
funcionó incluso si solo uso:result.encode().decode('unicode-escape')
Ammad Khalid
0

Ninguna respuesta funcionó para mi caso, donde tenía una variable de cadena que contenía caracteres unicode, y ninguna codificación-decodificación explicada aquí hizo el trabajo.

Si lo hago en una terminal

echo "no me llama mucho la atenci\u00f3n"

o

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

La salida es correcta:

output: no me llama mucho la atención

Pero trabajar con scripts que cargan esta variable de cadena no funcionó.

Esto es lo que funcionó en mi caso , en caso de que ayude a alguien:

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
fuente
necesitas importar json
pctripsesp