Python Language
Unicode et octets
Recherche…
Syntaxe
- str.encode (encodage, erreurs = 'strict')
- bytes.decode (encodage, erreurs = 'strict')
- ouvrir (nom de fichier, mode, codage = Aucun)
Paramètres
Paramètre | Détails |
---|---|
codage | Le codage à utiliser, par exemple 'ascii' , 'utf8' , etc ... |
les erreurs | Le mode des erreurs, par exemple 'replace' pour remplacer les mauvais caractères par des points d'interrogation, 'ignore' pour ignorer les mauvais caractères, etc ... |
Les bases
Dans Python 3, str
est le type des chaînes activées par Unicode, tandis que les bytes
sont le type des séquences d'octets bruts.
type("f") == type(u"f") # True, <class 'str'>
type(b"f") # <class 'bytes'>
Dans Python 2, une chaîne occasionnelle était une séquence d'octets bruts par défaut et la chaîne unicode correspondait à chaque chaîne avec le préfixe "u".
type("f") == type(b"f") # True, <type 'str'>
type(u"f") # <type 'unicode'>
Unicode en octets
Les chaînes Unicode peuvent être converties en octets avec .encode(encoding)
.
Python 3
>>> "£13.55".encode('utf8')
b'\xc2\xa313.55'
>>> "£13.55".encode('utf16')
b'\xff\xfe\xa3\x001\x003\x00.\x005\x005\x00'
Python 2
dans py2, l'encodage par défaut de la console est sys.getdefaultencoding() == 'ascii'
et non utf-8
comme dans py3, par conséquent, l'impression comme dans l'exemple précédent n'est pas directement possible.
>>> print type(u"£13.55".encode('utf8'))
<type 'str'>
>>> print u"£13.55".encode('utf8')
SyntaxError: Non-ASCII character '\xc2' in...
# with encoding set inside a file
# -*- coding: utf-8 -*-
>>> print u"£13.55".encode('utf8')
£13.55
Si l'encodage ne peut pas gérer la chaîne, un `UnicodeEncodeError` est généré:
>>> "£13.55".encode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character '\xa3' in position 0: ordinal not in range(128)
Octets à unicode
Les octets peuvent être convertis en chaînes Unicode avec .decode(encoding)
.
Une séquence d'octets ne peut être convertie en une chaîne Unicode que via le codage approprié!
>>> b'\xc2\xa313.55'.decode('utf8')
'£13.55'
Si le codage ne peut pas gérer la chaîne, une UnicodeDecodeError
est UnicodeDecodeError
:
>>> b'\xc2\xa313.55'.decode('utf16')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/csaftoiu/csaftoiu-github/yahoo-groups-backup/.virtualenv/bin/../lib/python3.5/encodings/utf_16.py", line 16, in decode
return codecs.utf_16_decode(input, errors, True)
UnicodeDecodeError: 'utf-16-le' codec can't decode byte 0x35 in position 6: truncated data
Gestion des erreurs d'encodage / décodage
.encode
et .decode
ont tous deux des modes d'erreur.
La valeur par défaut est 'strict'
, ce qui génère des exceptions en cas d'erreur. Les autres modes sont plus tolérants.
Codage
>>> "£13.55".encode('ascii', errors='replace')
b'?13.55'
>>> "£13.55".encode('ascii', errors='ignore')
b'13.55'
>>> "£13.55".encode('ascii', errors='namereplace')
b'\\N{POUND SIGN}13.55'
>>> "£13.55".encode('ascii', errors='xmlcharrefreplace')
b'£13.55'
>>> "£13.55".encode('ascii', errors='backslashreplace')
b'\\xa313.55'
Décodage
>>> b = "£13.55".encode('utf8')
>>> b.decode('ascii', errors='replace')
'��13.55'
>>> b.decode('ascii', errors='ignore')
'13.55'
>>> b.decode('ascii', errors='backslashreplace')
'\\xc2\\xa313.55'
Moral
Il ressort clairement de ce qui précède qu'il est essentiel de garder vos encodages corrects lorsque vous utilisez unicode et des octets.
Fichier I / O
Les fichiers ouverts en mode non binaire (par exemple, 'r'
ou 'w'
) traitent les chaînes. Le codage sourd est 'utf8'
.
open(fn, mode='r') # opens file for reading in utf8
open(fn, mode='r', encoding='utf16') # opens file for reading utf16
# ERROR: cannot write bytes when a string is expected:
open("foo.txt", "w").write(b"foo")
Les fichiers ouverts en mode binaire (par exemple 'rb'
ou 'wb'
) traitent les octets. Aucun argument de codage ne peut être spécifié car il n'y a pas de codage.
open(fn, mode='wb') # open file for writing bytes
# ERROR: cannot write string when bytes is expected:
open(fn, mode='wb').write("hi")