unicode_escape
ne fonctionne pas en général
Il s'avère que l' string_escape
ou unicode_escape
solution ne fonctionne pas en général-en particulier, il ne fonctionne pas en la présence réelle de l'Unicode.
Si vous pouvez être sûr que tous les caractères non-ASCII sera échappé (et n'oubliez pas, quelque chose au-delà les 128 premiers caractères non-ASCII), unicode_escape
va faire la bonne chose pour vous. Mais s'il y a des littérale des caractères non-ASCII déjà dans votre chaîne, les choses iront mal.
unicode_escape
est fondamentalement conçu pour convertir des octets dans le texte Unicode. Mais dans de nombreux endroits, par exemple, le code source Python -- la source de données est déjà de texte Unicode.
La seule façon cela ne peut fonctionner correctement si vous encoder le texte en octets de la première. UTF-8 est le sensible, codant pour l'ensemble du texte, de sorte que devrait fonctionner, non?
Les exemples suivants sont en Python 3, de sorte que les littéraux de chaîne sont plus propres, mais le même problème existe avec légèrement différentes manifestations sur Python 2 et 3.
>>> s = 'naïve \\t test'
>>> print(s.encode('utf-8').decode('unicode_escape'))
naïve test
Eh bien, c'est mal.
La nouvelle est recommandé d'utiliser des codecs qui décoder le texte dans le texte de l'appel codecs.decode
directement. Cela vous aide?
>>> import codecs
>>> print(codecs.decode(s, 'unicode_escape'))
naïve test
Pas du tout. (Aussi, le ci-dessus est un UnicodeError sur Python 2.)
L' unicode_escape
codec, en dépit de son nom, s'avère de supposer que tous les non-octets ASCII sont en Latin-1 (ISO-8859-1) codage. Donc, vous devez faire comme ceci:
>>> print(s.encode('latin-1').decode('unicode_escape'))
naïve test
Mais c'est terrible. Cela vous limite à 256 caractères Latin-1, comme si Unicode n'avait jamais été inventé à tous!
>>> print('Ernő \\t Rubik'.encode('latin-1').decode('unicode_escape'))
UnicodeEncodeError: 'latin-1' codec can't encode character '\u0151'
in position 3: ordinal not in range(256)
L'ajout d'une expression régulière pour résoudre le problème
(Étonnamment, nous n'avons deux problèmes.)
Ce que nous devons faire est seulement d'appliquer l' unicode_escape
décodeur de choses que nous sommes certains d'être en texte ASCII. En particulier, nous pouvons assurez-vous seulement de l'appliquer à Python valide les séquences d'échappement, qui sont garantis d'être de texte ASCII.
Le plan est, nous allons trouver des séquences d'échappement à l'aide d'une expression régulière, et d'utiliser une fonction comme argument d' re.sub
pour les remplacer par leur non échappés de la valeur.
import re
import codecs
ESCAPE_SEQUENCE_RE = re.compile(r'''
( \\U........ # 8-digit hex escapes
| \\u.... # 4-digit hex escapes
| \\x.. # 2-digit hex escapes
| \\[0-7]{1,3} # Octal escapes
| \\N\{[^}]+\} # Unicode characters by name
| \\[\\'"abfnrtv] # Single-character escapes
)''', re.UNICODE | re.VERBOSE)
def decode_escapes(s):
def decode_match(match):
return codecs.decode(match.group(0), 'unicode-escape')
return ESCAPE_SEQUENCE_RE.sub(decode_match, s)
Et avec ça:
>>> print(decode_escapes('Ernő \\t Rubik'))
Ernő Rubik