Convertir une chaîne Unicode en chaîne en Python (contenant des symboles supplémentaires)

504

Comment convertir une chaîne Unicode (contenant des caractères supplémentaires comme £ $, etc.) en une chaîne Python?

williamtroup
la source
2
Nous devons savoir quelle version de Python vous utilisez et ce que vous appelez une chaîne Unicode. Procédez comme suit sur une chaîne unicode_string courte qui inclut les symboles monétaires qui causent la gêne: Python 2.x: print type(unicode_string), repr(unicode_string)Python 3.x: Modifiez print type(unicode_string), ascii(unicode_string)ensuite votre question et copiez / collez les résultats de l'instruction d'impression ci-dessus. NE retapez PAS les résultats. Recherchez également en haut de votre code HTML et voyez si vous pouvez trouver quelque chose comme ceci: <meta http-equiv = "Content-Type" content = "text / html; charset = iso-8859
John Machin
3
Je doute que vous obteniez unicode à partir d'une demande Web. Vous obtenez probablement Unicode encodé en UTF-8.
28
@lutz: comment "Unicode codé UTF-8" n'est-il pas exactement unicode?
2011 à 10h09
2
Vous devriez vraiment clarifier ce que vous entendez par chaîne unicode et chaîne python (donner des exemples concrets serait le meilleur, je suppose), car il ressort clairement des commentaires qu'il existe différentes interprétations de votre question. Je me demande pourquoi vous ne l'avez pas fait, même si cela fait plus de 3,5 ans que vous avez posé cette question.
Piotr Dobrogost
6
@jalf: s'il est encodé ; ce n'est plus Unicode par exemple,unicode_string = u"I'm unicode string"; bytestring = unicode_string.encode('utf-8'); unicode_again = bytestring.decode('utf-8')
jfs

Réponses:

573

Voir 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
la source
24
+1 répond à la question telle qu'elle est libellée, le problème de @ williamtroup de ne pas pouvoir enregistrer unicode dans un fichier sonne comme un problème entièrement différent digne d'une question distincte
Mark Roddy
5
@John - cette réponse est antérieure à la clarification du PO.
Dominic Rodger
10
@Mark Roddy: Sa question telle qu'elle est écrite est de savoir comment convertir une "chaîne Unicode" (peu importe ce qu'il entend par là) contenant des symboles monétaires en une "chaîne Python" (peu importe ...) et vous pensez qu'une suppression de certains signes diacritiques delete-other-non-ascii characters kludge répond à sa question ???
John Machin
13
@JohnMachin Cela répond à la question mot pour mot: la seule façon de convertir une unicodechaîne en a strest de supprimer ou de convertir les caractères qui ne peuvent pas être représentés en ASCII. Donc +1 de moi.
Izkata
4
@lzkata: non, ce n'est pas le cas. type(title) == unicode and type(title.encode('utf-8')) == str. Pas besoin de corrompre l'entrée, pour obtenir un bytestring qui peut être enregistré dans un fichier.
jfs
319

Vous pouvez utiliser l'encodage en ASCII si vous n'avez pas besoin de traduire les caractères non ASCII:

>>> a=u"aaaàçççñññ"
>>> type(a)
<type 'unicode'>
>>> a.encode('ascii','ignore')
'aaa'
>>> a.encode('ascii','replace')
'aaa???????'
>>>
Ferran
la source
4
Réponse géniale. Exactement ce dont j'avais besoin. Aussi, une excellente présentation pour montrer l'effet du ignorevsreplace
Jonny Brooks
ou a.encode('ascii', 'xmlcharrefreplace')donne 'aaa&#224;&#231;&#231;&#231;&#241;&#241;&#241;'.
Bob Stein
type(a)est stren Python 3.6.8 et n'a aucune encode()méthode.
Ali Tou
138
>>> text=u'abcd'
>>> str(text)
'abcd'

Si la chaîne ne contient que des caractères ascii.

igco
la source
18
Cela ne fonctionnerait que sur les fenêtres. Et se cassera s'il y a des symboles non ascii.
Vanuan
6
Cela se casse si le contenu de la chaîne est en fait unicode, pas seulement des caractères ascii dans une chaîne unicode. Ne faites pas cela, vous obtiendrez des exceptions UnicodeEncodeError aléatoires partout.
Doug
11
Cette réponse m'a aidé. Si vous savez que votre chaîne est ascii et que vous devez la reconvertir en chaîne non unicode, cela est très utile.
VedTopkar
113

Si vous avez une chaîne Unicode et que vous souhaitez l'écrire dans un fichier ou tout autre formulaire sérialisé, vous devez d'abord la coder dans une représentation particulière qui peut être stockée. Il existe plusieurs codages Unicode courants, tels que UTF-16 (utilise deux octets pour la plupart des caractères Unicode) ou UTF-8 (1-4 octets / point de code selon le caractère), etc. Pour convertir cette chaîne en un codage particulier, vous peut utiliser:

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

Cette chaîne brute d'octets peut être écrite dans un fichier. Cependant, notez que lorsque vous le relisez, vous devez savoir dans quel encodage il se trouve et le décoder en utilisant ce même encodage.

Lors de l'écriture dans des fichiers, vous pouvez vous débarrasser de ce processus de codage / décodage manuel en utilisant le module codecs . Ainsi, pour ouvrir un fichier qui code toutes les chaînes Unicode en UTF-8 , utilisez:

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

Notez que tout autre élément utilisant ces fichiers doit comprendre l'encodage du fichier s'il souhaite les lire. Si vous êtes le seul à lire / écrire, ce n'est pas un problème, sinon assurez-vous que vous écrivez sous une forme compréhensible par tout ce qui utilise les fichiers.

Dans Python 3, cette forme d'accès aux fichiers est la valeur par défaut, et la openfonction intégrée prendra un paramètre d'encodage et se traduira toujours vers / depuis les chaînes Unicode (l'objet chaîne par défaut en Python 3) pour les fichiers ouverts en mode texte.

Brian
la source
58

Voici un exemple:

>>> u = u'€€€'
>>> s = u.encode('utf8')
>>> s
'\xe2\x82\xac\xe2\x82\xac\xe2\x82\xac'
Bastien Léonard
la source
1
Quelqu'un peut-il expliquer pourquoi, lorsque j'encode le symbole de l'euro utf8comme indiqué ici, le résultat n'est que des points d'interrogation? Voici une image de mon Python, version 2.7.13. (Je peux encoder d'autres objets Unicode comme u"Klüft", mais pas les Euros?)
The Red Pea
5

Eh bien, si vous êtes prêt / prêt à passer à Python 3 (ce qui n'est peut-être pas dû à l'incompatibilité en arrière avec du code Python 2), vous n'avez pas à effectuer de conversion; tout le texte en Python 3 est représenté avec des chaînes Unicode, ce qui signifie également qu'il n'y a plus d'utilisation de la u'<text>'syntaxe. Vous avez également des chaînes d'octets qui sont utilisées pour représenter des données (qui peuvent être une chaîne codée).

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

(Bien sûr, si vous utilisez actuellement Python 3, le problème est probablement lié à la façon dont vous essayez d'enregistrer le texte dans un fichier.)

COUP
la source
2
En Python 3, les chaînes sont des chaînes Unicode. Ils ne sont jamais encodés. J'ai trouvé le texte suivant utile: joelonsoftware.com/articles/Unicode.html
Il veut l'enregistrer dans un fichier; comment votre réponse aide-t-elle à cela?
John Machin
@lutz: Oui, j'avais oublié qu'Unicode est une carte de caractères plutôt qu'un encodage. @John: Il n'y a pas assez d'informations pour le moment pour savoir quel est le problème avec la sauvegarde. Obtient-il une erreur? N'obtient-il pas d'erreurs, mais lors de l'ouverture du fichier en externe, il obtient mojibake? Sans ces informations, il existe bien trop de solutions possibles qui pourraient être apportées.
JAB
@Cat: Il n'y a aucune information pour le moment pour savoir ce qu'il a, et encore moins quel est son problème d'épargne. Je lui ai demandé de fournir certains faits - voir ma réponse.
John Machin
5

Voici un exemple de code

import unicodedata    
raw_text = u"here $%6757 dfgdfg"
convert_text = unicodedata.normalize('NFKD', raw_text).encode('ascii','ignore')
Gihan Chathuranga
la source
en quoi cette réponse est différente de la réponse acceptée?
sgauri
3

le fichier contient une chaîne au format unicode

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

pour moi

 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
la source
2
cela a fonctionné même si je n'utilise que:result.encode().decode('unicode-escape')
Ammad Khalid
0

Aucune réponse n'a fonctionné pour mon cas, où j'avais une variable de chaîne contenant des caractères unicode, et aucun encodage-décodage expliqué ici n'a fait le travail.

Si je le fais dans un terminal

echo "no me llama mucho la atenci\u00f3n"

ou

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

La sortie est correcte:

output: no me llama mucho la atención

Mais travailler avec des scripts chargeant cette variable de chaîne n'a pas fonctionné.

C'est ce qui a fonctionné sur mon cas , au cas où cela aiderait quelqu'un:

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
la source
vous devez importer json
pctripsesp