web-dev-qa-db-fra.com

Python "string_escape" vs "unicode_escape"

Selon la documentation , la chaîne intégrée codant string_escape:

Produire [s] une chaîne qui convient comme littéral de chaîne dans Python

...tandis que le unicode_escape:

Produisez [s] une chaîne qui convient comme littéral Unicode dans Python

Ainsi, ils devraient avoir à peu près le même comportement. MAIS, ils semblent traiter différemment les guillemets simples:

>>> print """before '" \0 after""".encode('string-escape')
before \'" \x00 after
>>> print """before '" \0 after""".encode('unicode-escape')
before '" \x00 after

Le string_escape échappe à la citation unique, contrairement à celle d'Unicode. Est-il sûr de supposer que je peux simplement:

>>> escaped = my_string.encode('unicode-escape').replace("'", "\\'")

... et obtenir le comportement attendu?

Edit: Juste pour être très clair, le comportement attendu devient quelque chose de convenable comme littéral.

24
Mike Boers

Selon mon interprétation de l'implémentation de unicode-escape Et de l'unicode repr dans la source CPython 2.6.5, oui; la seule différence entre repr(unicode_string) et unicode_string.encode('unicode-escape') est l'inclusion de guillemets enveloppants et l'échappement quelle que soit la citation utilisée.

Ils sont tous deux pilotés par la même fonction, unicodeescape_string. Cette fonction prend un paramètre dont la seule fonction est de basculer l'ajout des guillemets enveloppants et l'échappement de ce guillemet.

22
Mike Boers

Dans la plage 0 ≤ c <128, oui, le ' est la seule différence pour CPython 2.6.

>>> set(unichr(c).encode('unicode_escape') for c in range(128)) - set(chr(c).encode('string_escape') for c in range(128))
set(["'"])

En dehors de cette plage, les deux types ne sont pas échangeables.

>>> '\x80'.encode('string_escape')
'\\x80'
>>> '\x80'.encode('unicode_escape')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can’t decode byte 0x80 in position 0: ordinal not in range(128)

>>> u'1'.encode('unicode_escape')
'1'
>>> u'1'.encode('string_escape')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: escape_encode() argument 1 must be str, not unicode

Sur Python 3.x, le string_escape l'encodage n'existe plus, car str ne peut stocker que Unicode.

12
kennytm