Le codage des caract`
eres en Python
Olivier Iffrig
2 novembre 2014
Licence
Cet article, ainsi que les images qu’il contient (sauf mention contraire explicite) sont
sous licence Creative Commons CC-BY-SA. Vous pouvez le copier et le modifier `
a votre
guise, `
a condition de citer l’auteur, de mettre en ´
evidence vos modifications et de partager
les modifications sous la mˆ
eme licence. Pour plus de d´
etails : http://creativecommons.
org/licenses/by-sa/4.0/
1 Le co— quoi ?
Nos ordinateurs ne comprennent que le binaire, c’est `
a dire des 0 et des 1 1, souvent
regroup´
es par 8 (les octets).
Pour pouvoir repr´
esenter du texte dans ce syst`
eme, il faut donc choisir une repr´
esen-
tation pour chaque caract`
ere. C’est ce qu’ont fait un certain nombre de gens, et vous vous
imaginez bien qu’ils ne se sont pas concert´
es avant, du coup, `
a la fin des ann´
ees 50, chacun
avait sa propre convention de codage des caract`
eres.
Afin d’arranger un peu les choses, l’ISO a d´
ecid´
e en 1960 de cr´
eer un comit´
e charg´
e des
syst`
emes d’information, dont l’un des objectifs ´
etait de coordonner les diff´
erentes conven-
tions de codage. C’est ainsi que naˆ
ıt l’American Standard Code for Information Interchange,
abr´
eg´
e ASCII.
1. pouvant ˆ
etre repr´
esent´
es physiquement de diverses mani`
eres, par exemple un potentiel ´
electrique inf´
erieur
ou sup´
erieur `
a un seuil donn´
e
1
.0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F
0. NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI
1. DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
2. SP ! # $ % & ( ) * + , - . /
3. 0 1 2 3 4 5 6 7 8 9 : ; <=>?
4. @ A B C D E F G H I J K L M N O
5. P Q R S T U V W X Y Z [ \] ˆ
6. ` a b c d e f g h i j k l m n o
7. p q r s t u v w x y z {}˜DEL
La table des caract`
eres ASCII
L’ASCII permet de repr´
esenter sur 7 bits (que l’on pr´
efixe en g´
en´
eral par un 0 pour com-
pl´
eter l’octet) les caract`
eres usuels de la langue anglaise, c’est-`
a-dire les lettres majuscules
et minuscules, les chiffres, quelques symboles de ponctuation, ainsi que des caract`
eres de
contrˆ
ole servant `
a modifier le comportement des terminaux 2.
UnicodeDecodeError : ’ascii’ codec can’t decode byte 0xc3 in position 7 : ordinal not in range(128)
´
Etant donn´
e que beaucoup de langues utilisent des caract`
eres ne figurant pas dans
l’ASCII, des extensions ont ´
et´
e propos´
ees afin de pallier ce manque. Une fois de plus, les
diverses extensions n’´
etaient pas toujours compatibles entre elles, et nous voil`
a revenus `
a
notre point de d´
epart.
c
XKCD, http://xkcd.com/927
Bref, il existe beaucoup de codages possibles pour repr´
esenter du texte. Et je ne parle
mˆ
eme pas de le manipuler. Imaginons que vous voulez r´
e´
ecrire un mot en lettres capi-
tales. Tant qu’il s’agit de caract`
eres ASCII, il suffit d’enlever 32 aux caract`
eres entre 97 et
2. Oui, `
a l’´
epoque, les ordinateurs ´
etaient quelque peu encombrants, donc les op´
erateurs disposaient d’un
clavier et d’un ´
ecran permettant de les contrˆ
oler depuis un bureau.
2
122 (les lettres minuscules). Mais comment faire si c’est une autre lettre ? C¸ a d´
epend du
codage utilis´
e. Et rien ne nous garantit que la capitale correspondante peut elle aussi ˆ
etre
repr´
esent´
ee. Et puis, qu’est-ce qui me dit que je ne suis pas en train d’utiliser une lettre
diff´
erente dessin´
ee de la mˆ
eme fac¸on ?
U+0399 GREEK CAPITAL LETTER IOTA
Tous ces probl`
emes trouvent une solution avec le standard Unicode, qui associe d’une
part un nom `
a chaque caract`
ere (abstrait), et d’autre part un num´
ero, appel´
epoint de code.
Ainsi, si on connaˆ
ıt la correspondance entre une convention de codage et les points de code
de chacun des caract`
eres, la manipulation devient plus ais´
ee.
De mani`
ere `
a pouvoir repr´
esenter ais´
ement les caract`
eres Unicode, on peut bien sˆ
ur
utiliser le codage que l’on veut. Il en existe cependant trois qui ont ´
et´
e pr´
evus de mani`
ere `
a
faciliter les choses. Il s’agit d’UTF-8, UTF-16 et UTF-32, utilisant comme unit´
e de base 8, 16
ou 32 bits (je dis bien unit´
e de base, parce qu’un caract`
ere peut n´
ecessiter plusieurs unit´
es),
et qui peuvent encoder n’importe quel caract`
ere Unicode.
2 Et Python dans tout ¸ca ?
En Python 2.x, il existe deux types de chaˆ
ınes de caract`
eres : str et unicode. Les deux
peuvent servir `
a repr´
esenter des caract`
eres. Comme vous l’aurez devin´
e, unicode sert `
a
repr´
esenter des chaˆ
ınes de caract`
eres Unicode. Par opposition, comme son nom ne l’in-
dique pas, str devrait servir `
a repr´
esenter des suites d’octets, dont certaines sont, de mani`
ere
fortuite, des repr´
esentations encod´
ees d’une chaˆ
ıne de caract`
eres. En Python 3, la notation
est clarifi´
ee puisque les chaˆ
ınes Unicode sont rebaptis´
ees str, alors que les suites d’octets
prennent le type bytes.
Python 2 Python 3 σ ο φ ί α
unicode str 03C3 03BF 03C6 03AF 03B1
str bytes CF83 CEBF CF86 CEAF CEB1
Un exemple en UTF-8
.encode(”utf8”).decode(”utf8”)
En pratique, pour passer d’une chaˆ
ıne d’octets `
a une chaˆ
ıne Unicode, il faut utiliser
la m´
ethode decode, qui prend en argument le nom du codage utilis´
e (et aussi la mani`
ere
3
de traiter les erreurs, je vous laisse lire la documentation si c¸a vous int´
eresse). Le passage
d’une chaˆ
ıne Unicode `
a une chaˆ
ıne d’octets se fait via la m´
ethode encode qui fonctionne
de la mˆ
eme fac¸on.
b = \xc3\xa9 # un ” ´e en UTF8
s = b . decode ( ” utf 8)# un ´e ” r e p r ´e s e n t ´e en Uni code (U+00E9 )
S = s . upper ( ) # un ” ´
E r e p r ´e s e n t ´e en Unic ode (U+00C9 )
B = S . encode ( ” utf 8” )# un ” ´
E en UTF8 ( C389 )
Lorsqu’on veut repr´
esenter du texte, il est donc fortement recommand´
e d’utiliser des
chaˆ
ınes Unicode le plus longtemps possible, et de ne choisir un encodage que pour impor-
ter ou exporter le texte (dans un fichier ou via un r´
eseau, par exemple). Que ce soit pour
du texte ou des suites d’octets, il est primordial de bien savoir ce que l’on manipule afin
d’´
eviter les confusions. Surtout en Python 2 o `
u le passage entre str et unicode peut ˆ
etre
implicite (et source d’erreurs cryptiques et difficiles `
a rep´
erer).
Le sandwich unicode
2.1 Mauvaises pratiques
1. Une fonction universelle de conversion (Python 2.x, a son ´
equivalent en Python
3.x)
def convert everything to unicode (x ):
i f i s i n s t a n c e ( x , unicode ) :
return x
e l s e :
return s t r ( x ) . decode ( ut f 8 ’ )
Cette fonction n’est pas fondamentalement mauvaise, puisqu’elle sert `
a convertir
une chaˆ
ıne d’octets en chaˆ
ıne Unicode. Cependant, elle n’aide en rien `
a connaˆ
ıtre
le contenu de x, et donc devient dangereuse si utilis´
ee n’importe o `
u. De plus, elle
pr´
esuppose que la chaˆ
ıne d’octets encode un texte en UTF-8, ce qui n’est pas n´
e-
cessairement le cas (sauf convention d’usage, qui doit dans ce cas ˆ
etre clairement
explicit´
ee). Enfin, elle op`
ere une conversion en chaˆ
ıne d’octets, ce qui ouvre la porte
`
a beaucoup de mauvaises utilisations. Mˆ
eme remarque pour la fonction inverse :
def c o n v e r t e v e r y t h i n g t o s t r ( x ) :
i f isinstance ( x , s t r ) :
4
return x
e l s e :
return unicode ( x ) . encode ( utf 8 ’ )
2. M´
elanger str et unicode (Python 2.x uniquement)
def p r i n t r e s u l t ( r ) :
print uR´
e s u l t a t : +str (r)
Cette fonction pr´
esente deux points de danger : premi`
erement, l’op´
erateur + op´
er´
e
entre un str et un unicode, qui entraˆ
ıne une conversion implicite du str en unicode.
Si par malheur, str (r) renvoie une chaˆ
ıne d’octets contenant des octets de valeur
num´
erique sup´
erieure `
a 127, une erreur serait lanc´
ee :
UnicodeDecodeError : a s c i i codec can t decode byte 0 xc3 in
p o s i t i o n 0 : o r di n al not i n range ( 1 2 8 )
Deuxi`
emement, l’erreur inverse risque de se produire si l’encodage de la chaˆ
ıne
Unicode demand´
e implicitement par print ´
echoue (souvent parce que l’encodage
de la sortie standard n’est pas connu ou est plus restrictif que n´
ecessaire) :
UnicodeEncodeError : a s c i i codec can t encode c h a r a c t e r u ’ \
xe9 i n p o s i t i o n 0 : o r d in a l not i n range ( 1 2 8 )
Ces probl`
emes sont r´
esolus en Python 3.x, o `
u aucune conversion entre bytes et str
n’est faite implicitement. On a donc une erreur lorsqu’on essaie par exemple de
concat´
ener une chaˆ
ıne d’octets et une chaˆ
ıne de caract`
eres Unicode, quel que soit le
contenu des chaˆ
ınes.
2.2 Quelques conseils
1. Fichiers texte
En Python 2.x, on peut manipuler des fichiers texte `
a l’aide du module codecs qui
permet de sp´
ecifier un codage lors de l’ouverture du fichier :
import codecs
with codecs .open ( t o t o . t x t ,w, encoding=” u tf 8” )as f :
f . w ri te ( uEnchant \u00e9 . \n)
Attention cependant, en utilisant le module codecs, on perd la conversion automa-
tique des fins de ligne.
En Python 3.x, la fonction open dispose d’un argument encoding qui permet d’uti-
liser directement ce que permettait codecs.open en Python 2.x. On peut ´
egalement
noter que les retours `
a la ligne peuvent ˆ
etre convertis automatiquement, contraire-
ment aux fichiers ouverts avec le module codecs.
with open ( t o t o . t x t ,w, encoding=” u tf 8” )as f :
f . wr it e ( Enchant\u00e9 . \n)
5
1 / 6 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !