unicode et encodage et charset et je perds mon latin-1

Le
Laurent FRANCOIS
Bonjour,

J'ai un probleme de charset

J'ai pas mal lu sur l'unicode et autre charset.
j'ai pas tout compris sinon je serais pas là pour
poser une question.

Voila mon probleme.

class Movie(object):
def __init__(self, title):
self.title = title
def __repr__(self):
return "<Movie: %s>" %(self.title)

>>> ins = Movie("ééééé")
>>> ins
<Movie: ééééé>
>>> uins = Movie(u"ééééé")
>>> uins
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position
8-12: ordinal not in range(128)




>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>> sys.version
'2.5.5 (r255:77872, Apr 21 2010, 08:40:04) [GCC 4.4.3]'
>>>
Je suis sous debian squeeze et
#locale:
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
eb303
Le #22317961
On Jul 1, 8:08 am, Laurent FRANCOIS wrote:
Bonjour,

J'ai un probleme de charset

J'ai pas  mal lu sur l'unicode et autre charset.
j'ai pas tout compris sinon je serais pas là pour
poser une question.

Voila mon probleme.

class Movie(object):
...     def __init__(self, title):
...             self.title = title
...     def __repr__(self):
...             return "<Movie: %s>" %(self.title)
...
 >>> ins = Movie("ééééé")
 >>> ins
<Movie: ééééé>
 >>> uins = Movie(u"ééééé")
 >>> uins
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position
8-12: ordinal not in range(128)

 >> import sys
 >>> sys.getdefaultencoding()
'ascii'
 >>> sys.version
'2.5.5 (r255:77872, Apr 21 2010, 08:40:04) n[GCC 4.4.3]'



Assez simple en fait: quand tu demandes d'afficher uins, Python
appelle __repr__, qui fait "<Movie: %s>" %(self.title), et self.title
est une chaîne unicode. Vu que <Movie: %s>" n'en est pas une, Python
va essayer de représenter self.title en "byte string" pour pouvoir la
rentrer dans le %s, ce pour quoi il doit l'encoder. L'encodage par
défaut étant ASCII, il va faire en gros self.title.encode('ascii'), ce
qui évidemment ne fonctionne pas vu que self.title contient des
caractères accentués qui ne sont pas dans le jeu de caractère ASCII.
En fait, au final, Python fera:
u'ééééé'.encode('ascii')






Ce qui donne ce que tu as vu:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position
0-4: ordinal not in range(128)

Voilà pour le problème. Pour la solution, c'est une autre histoire, et
ça dépend de ce que tu veux faire en fait. La première chose serait d e
passer toutes tes chaînes en chaînes unicode, et donc de modifier la
méthode __repr__ comme ça:
def __repr__(self):
return u"<Movie: %s>" %(self.title)
De cette façon, pas d'encodage quand self.title sera une chaîne
Unicode: elle rentre toute seule dans le %s. Dans ce cas précis, ça ne
posera pas de problème, vu que "<Movie: %s>" ne contient que des
caratères ASCII. Par contre, si tu essaies d'utiliser autre chose,
genre u'ééééé', voilà ce qui se passera quand tu lanceras ton
programme:
File "toto.py", line 1
SyntaxError: Non-ASCII character 'xc3' in file toto.py on line 1, but
no encoding declared; see http://www.python.org/peps/pep-0263.html for
details
Ce qui se passe ici, c'est que tu as une chaîne unicode contenant des
caractères non-ASCII. Ces caractères sont encodés avec un certain
encodage dans ton fichier, décidé probablement par ton éditeur de cod e
source; mais Python n'a aucune idée de ce que c'est. Vu qu'essayer de
deviner n'est pas dans la philosophie du langage, il préfère s'arrête r
tout de suite et te renvoyer une erreur de syntaxe. La solution est
d'indiquer à Python l'encodage de tes fichiers sources à l'aide de la
ligne magique:
# -*- coding: … -*-
à placer en début de fichier. Bien sûr, remplacer les … par l'encod age
par défaut de ton éditeur préféré (que je ne connais pas, donc je ne
peux pas t'aider là-dessus). Et je te conseille la lecture de la page
citée dans l'erreur ci-dessus (http://www.python.org/peps/
pep-0263.html).

L'autre solution, c'est de passer à Python 3, et là toutes tes chaîne s
seront des chaînes unicode par défaut et tu n'auras plus à tout
préfixer par des u partout. Mais ça ne changera rien à la nécessit é de
déclarer ton encodage dans tes sources…

J'espère que c'est un peu plus clair.
- Eric -
NicolasP
Le #22318771
Le 01/07/2010 10:58, eb303 a écrit :
On Jul 1, 8:08 am, Laurent FRANCOIS wrote:
Bonjour,

J'ai un probleme de charset

J'ai pas mal lu sur l'unicode et autre charset.
j'ai pas tout compris sinon je serais pas là pour
poser une question.

Voila mon probleme.

class Movie(object):
... def __init__(self, title):
... self.title = title
... def __repr__(self):
... return "<Movie: %s>" %(self.title)
...
>>> ins = Movie("ééééé")
>>> ins
<Movie: ééééé>
>>> uins = Movie(u"ééééé")
>>> uins
Traceback (most recent call last):
File "<stdin>", line 1, in<module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position
8-12: ordinal not in range(128)

>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>> sys.version
'2.5.5 (r255:77872, Apr 21 2010, 08:40:04) n[GCC 4.4.3]'



Assez simple en fait: quand tu demandes d'afficher uins, Python
appelle __repr__, qui fait "<Movie: %s>" %(self.title), et self.title
est une chaîne unicode. Vu que<Movie: %s>" n'en est pas une, Python
va essayer de représenter self.title en "byte string" pour pouvoir la
rentrer dans le %s, ce pour quoi il doit l'encoder. L'encodage par
défaut étant ASCII, il va faire en gros self.title.encode('ascii'), ce
qui évidemment ne fonctionne pas vu que self.title contient des
caractères accentués qui ne sont pas dans le jeu de caractère ASCII.
En fait, au final, Python fera:
u'ééééé'.encode('ascii')






Ce qui donne ce que tu as vu:
Traceback (most recent call last):
File "<stdin>", line 1, in<module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position
0-4: ordinal not in range(128)

Voilà pour le problème. Pour la solution, c'est une autre histoire, et
ça dépend de ce que tu veux faire en fait. La première chose serait de
passer toutes tes chaînes en chaînes unicode, et donc de modifier la
méthode __repr__ comme ça:
def __repr__(self):
return u"<Movie: %s>" %(self.title)
De cette façon, pas d'encodage quand self.title sera une chaîne
Unicode: elle rentre toute seule dans le %s. Dans ce cas précis, ça ne
posera pas de problème, vu que "<Movie: %s>" ne contient que des
caratères ASCII. Par contre, si tu essaies d'utiliser autre chose,
genre u'ééééé', voilà ce qui se passera quand tu lanceras ton
programme:
File "toto.py", line 1
SyntaxError: Non-ASCII character 'xc3' in file toto.py on line 1, but
no encoding declared; see http://www.python.org/peps/pep-0263.html for
details
Ce qui se passe ici, c'est que tu as une chaîne unicode contenant des
caractères non-ASCII. Ces caractères sont encodés avec un certain
encodage dans ton fichier, décidé probablement par ton éditeur de code
source; mais Python n'a aucune idée de ce que c'est. Vu qu'essayer de
deviner n'est pas dans la philosophie du langage, il préfère s'arrêter
tout de suite et te renvoyer une erreur de syntaxe. La solution est
d'indiquer à Python l'encodage de tes fichiers sources à l'aide de la
ligne magique:
# -*- coding: … -*-
à placer en début de fichier. Bien sûr, remplacer les … par l'encodage
par défaut de ton éditeur préféré (que je ne connais pas, donc je ne
peux pas t'aider là-dessus). Et je te conseille la lecture de la page
citée dans l'erreur ci-dessus (http://www.python.org/peps/
pep-0263.html).

L'autre solution, c'est de passer à Python 3, et là toutes tes chaînes
seront des chaînes unicode par défaut et tu n'auras plus à tout
préfixer par des u partout. Mais ça ne changera rien à la nécessité de
déclarer ton encodage dans tes sources…

J'espère que c'est un peu plus clair.
- Eric -



Un peu de littérature...

Unicode, ça fait peur fait en fait c'est tout simple (ou presque) quand on a compris les concepts de base.
- ASCII : Caractères codés sur 7 bits donc de 0 à 127. A chaque valeur numérique, correspond un caractère. Normalement, la table de correspondance est la même pour tout le monde.
- ASCII étendu : Caractères codés sur 8 bits dont la valeur numérique va de 128 à 255. La table de correspondance n'est pas la même pour tout le monde. Elle dépend du "code page" utilisé.
- Unicode est une norme qui définit une table de correspondance entre des valeurs numériques et des caractères sans limite. A chaque caractère correspond une valeur numérique. Mais les valeurs numériques Unicode n'ont PAS de taille (en terme de bits). Ce ne sont pas des 8 bits ni des 16 bits ni rien d'autre.
- L'encodage permet de définir une représentation physique (en bits) d'un caractère Unicode. Et évidemment, il n'y en a pas qu'un seul d'encodage. UTF8, UTF16, UTF32, Latin-1... UTF8 est un des plus utilisés. L'encodage est obligatoire. Il faut bien un moyen de représenter des valeurs numériques physiquement. Mais une chaine Unicode encodée (une suite de 8bits ou 16bits ou...) ne contient pas l'information de codage. Et c'est là que ça coince souvent. De plus, une chaine Unicode encodée n'est plus manipulable. Il faut la décoder pour pouvoir la manipuler à nouveau.

Si l'on prend l'exemple d'un programme Python :
- Le code source se trouve dans un fichier. Ce fichier contient des caractères qui sont encodés par l'éditeur de fichier (vim, notepad, eclipse...). Ca ne peut pas être autrement. L'éditeur de fichier doit encoder les caractères pour pouvoir les écrire dans le fichier qui est composé d'une suite d'octets.
Il est souvent possible de spécifier à l'éditeur de fichier quel encodage il doit utiliser. Mais le type d'encodage utilisé n'est pas spécifié dans le fichier. La solution trouvée par les développeurs du langage est de mettre cette information en commentaire au début du fichier (# -*- coding: … -*-). Il faut prendre garde à bien spécifier l'encodage utilisé par l'éditeur de fichier sinon ça va coincer quelque part. Il y a des éditeurs qui savent interpréter la ligne de commentaire et enregistrer le fichier avec l'encodage spécifié dans cette dernière.
- Python 2.x définit des chaines de caractères "ASCII" ("") (plus exactement byte string) et des chaines de caractères Unicode (u""). Les chaines de caractères Unicode sont décodées par l'interpréteur Python en utilisant l'encodage définit dans la première ligne de commentaire. D'où l'importance que cette ligne soit bien écrite. Si l'info d'encodage est erronnée, il y aura un mauvais décodage, voir une exception. Les chaines de caractères "byte string" sont traitées comme "un octet = un caractère" par l'interpréteur Python.
Par exemple, avec un encodage UTF8, le caractère € est constitué de la suite d'octets 0xE2, 0x82, 0xAC dans le fichier et donc dans la byte string. La chaine "€" contient 3 caractères du point de vu de l'interpréteur Python. Alors que la chaine u"€" contient un caractère du point de vu de l'interpréteur Python.
- Python 3.x ne connait que des chaines de caractères Unicode et l'encodage par défaut est UTF8.

Enfin, Unicode ne définissant pas une méthode de représentation physique des valeurs associées aux caractères, comment l'interpréteur Python fait t-il pour stocker les chaines Unicode décodées en interne ? Eh bien les programmeurs de l'interpréteur se sont définit une méthode de représentation à eux (que je ne connais pas) et cela ne concerne en rien les utilisateurs (les programmeurs Python que nous sommes). Le principal étant que les chaines Unicode soient gérées correctement.

Nicolas
Laurent FRANCOIS
Le #22321851
tu as essayé :

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# j'ai mis utf-8 à la place de ...
# mon editeur "emacs 23"

class Movie(object):
def __init__(self, title):
self.title = title
def __repr__(self):
return u"<Movie: %s>" %(self.title)

Et ça marche?

Parce que chez moi ça ne marche pas.
Ni en script ni en interactif sur un terminal
ni en interactif avec PyCrust.

Merci

Mon editeur emacs 23
le coding :

Coding system for saving this buffer:
Not set locally, use the default.
Default coding system (for new files):
U -- utf-8-unix (alias: mule-utf-8-unix)

Coding system for keyboard input:
= -- no-conversion (alias: binary)

Coding system for terminal output:
nil
Coding system for inter-client cut and paste:
nil
Defaults for subprocess I/O:
decoding: U -- utf-8-unix (alias: mule-utf-8-unix)

encoding: U -- utf-8-unix (alias: mule-utf-8-unix)


et
$locale

LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL
On 07/01/2010 07:58 PM, eb303 wrote:
On Jul 1, 8:08 am, Laurent FRANCOIS wrote:
Bonjour,

J'ai un probleme de charset

J'ai pas mal lu sur l'unicode et autre charset.
j'ai pas tout compris sinon je serais pas là pour
poser une question.

Voila mon probleme.

class Movie(object):
... def __init__(self, title):
... self.title = title
... def __repr__(self):
... return "<Movie: %s>" %(self.title)
...
>>> ins = Movie("ééééé")
>>> ins
<Movie: ééééé>
>>> uins = Movie(u"ééééé")
>>> uins
Traceback (most recent call last):
File "<stdin>", line 1, in<module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position
8-12: ordinal not in range(128)

>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>> sys.version
'2.5.5 (r255:77872, Apr 21 2010, 08:40:04) n[GCC 4.4.3]'



Assez simple en fait: quand tu demandes d'afficher uins, Python
appelle __repr__, qui fait "<Movie: %s>" %(self.title), et self.title
est une chaîne unicode. Vu que<Movie: %s>" n'en est pas une, Python
va essayer de représenter self.title en "byte string" pour pouvoir la
rentrer dans le %s, ce pour quoi il doit l'encoder. L'encodage par
défaut étant ASCII, il va faire en gros self.title.encode('ascii'), ce
qui évidemment ne fonctionne pas vu que self.title contient des
caractères accentués qui ne sont pas dans le jeu de caractère ASCII.
En fait, au final, Python fera:
u'ééééé'.encode('ascii')






Ce qui donne ce que tu as vu:
Traceback (most recent call last):
File "<stdin>", line 1, in<module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position
0-4: ordinal not in range(128)

Voilà pour le problème. Pour la solution, c'est une autre histoire, et
ça dépend de ce que tu veux faire en fait. La première chose serait de
passer toutes tes chaînes en chaînes unicode, et donc de modifier la
méthode __repr__ comme ça:
def __repr__(self):
return u"<Movie: %s>" %(self.title)
De cette façon, pas d'encodage quand self.title sera une chaîne
Unicode: elle rentre toute seule dans le %s. Dans ce cas précis, ça ne
posera pas de problème, vu que "<Movie: %s>" ne contient que des
caratères ASCII. Par contre, si tu essaies d'utiliser autre chose,
genre u'ééééé', voilà ce qui se passera quand tu lanceras ton
programme:
File "toto.py", line 1
SyntaxError: Non-ASCII character 'xc3' in file toto.py on line 1, but
no encoding declared; see http://www.python.org/peps/pep-0263.html for
details
Ce qui se passe ici, c'est que tu as une chaîne unicode contenant des
caractères non-ASCII. Ces caractères sont encodés avec un certain
encodage dans ton fichier, décidé probablement par ton éditeur de code
source; mais Python n'a aucune idée de ce que c'est. Vu qu'essayer de
deviner n'est pas dans la philosophie du langage, il préfère s'arrêter
tout de suite et te renvoyer une erreur de syntaxe. La solution est
d'indiquer à Python l'encodage de tes fichiers sources à l'aide de la
ligne magique:
# -*- coding: … -*-
à placer en début de fichier. Bien sûr, remplacer les … par l'encodage
par défaut de ton éditeur préféré (que je ne connais pas, donc je ne
peux pas t'aider là-dessus). Et je te conseille la lecture de la page
citée dans l'erreur ci-dessus (http://www.python.org/peps/
pep-0263.html).

L'autre solution, c'est de passer à Python 3, et là toutes tes chaînes
seront des chaînes unicode par défaut et tu n'auras plus à tout
préfixer par des u partout. Mais ça ne changera rien à la nécessité de
déclarer ton encodage dans tes sources…

J'espère que c'est un peu plus clair.
- Eric -
NicolasP
Le #22322041
Le 02/07/2010 12:08, Laurent FRANCOIS a écrit :
tu as essayé :

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# j'ai mis utf-8 à la place de ...
# mon editeur "emacs 23"

class Movie(object):
def __init__(self, title):
self.title = title
def __repr__(self):
return u"<Movie: %s>" %(self.title)

Et ça marche?

Parce que chez moi ça ne marche pas.
Ni en script ni en interactif sur un terminal
ni en interactif avec PyCrust.



Et non, ça ne marche pas.
Il semblerait qu'il y ait un bug à ce niveau.
Tout se comporte comme si repr() retournait un type byte string mais avec un contenu Unicode.

Tu as 2 solutions :

1) print "%s" % uins

2) Encoder les chaines de caractères dans __repr__():
#!/usr/bin/env python
# -*- coding: UTF8 -*-
# j'ai mis utf-8 à la place de ...
# mon editeur "emacs 23"

import sys

class Movie(object):
def __init__(self, title):
self.title = title
def __repr__(self):
r = u"<Movie: %s>" %(self.title)
return r.encode(sys.stdout.encoding)

uins = Movie(u"ééééé")
print "%s" % uins
print Movie(u"ééééé")



Nicolas



Merci

Mon editeur emacs 23
le coding :

Coding system for saving this buffer:
Not set locally, use the default.
Default coding system (for new files):
U -- utf-8-unix (alias: mule-utf-8-unix)

Coding system for keyboard input:
= -- no-conversion (alias: binary)

Coding system for terminal output:
nil
Coding system for inter-client cut and paste:
nil
Defaults for subprocess I/O:
decoding: U -- utf-8-unix (alias: mule-utf-8-unix)

encoding: U -- utf-8-unix (alias: mule-utf-8-unix)


et
$locale

LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL >
On 07/01/2010 07:58 PM, eb303 wrote:
On Jul 1, 8:08 am, Laurent FRANCOIS wrote:
Bonjour,

J'ai un probleme de charset

J'ai pas mal lu sur l'unicode et autre charset.
j'ai pas tout compris sinon je serais pas là pour
poser une question.

Voila mon probleme.

class Movie(object):
... def __init__(self, title):
... self.title = title
... def __repr__(self):
... return "<Movie: %s>" %(self.title)
...
>>> ins = Movie("ééééé")
>>> ins
<Movie: ééééé>
>>> uins = Movie(u"ééééé")
>>> uins
Traceback (most recent call last):
File "<stdin>", line 1, in<module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position
8-12: ordinal not in range(128)

>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>> sys.version
'2.5.5 (r255:77872, Apr 21 2010, 08:40:04) n[GCC 4.4.3]'



Assez simple en fait: quand tu demandes d'afficher uins, Python
appelle __repr__, qui fait "<Movie: %s>" %(self.title), et self.title
est une chaîne unicode. Vu que<Movie: %s>" n'en est pas une, Python
va essayer de représenter self.title en "byte string" pour pouvoir la
rentrer dans le %s, ce pour quoi il doit l'encoder. L'encodage par
défaut étant ASCII, il va faire en gros self.title.encode('ascii'), ce
qui évidemment ne fonctionne pas vu que self.title contient des
caractères accentués qui ne sont pas dans le jeu de caractère ASCII.
En fait, au final, Python fera:
u'ééééé'.encode('ascii')






Ce qui donne ce que tu as vu:
Traceback (most recent call last):
File "<stdin>", line 1, in<module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position
0-4: ordinal not in range(128)

Voilà pour le problème. Pour la solution, c'est une autre histoire, et
ça dépend de ce que tu veux faire en fait. La première chose serait de
passer toutes tes chaînes en chaînes unicode, et donc de modifier la
méthode __repr__ comme ça:
def __repr__(self):
return u"<Movie: %s>" %(self.title)
De cette façon, pas d'encodage quand self.title sera une chaîne
Unicode: elle rentre toute seule dans le %s. Dans ce cas précis, ça ne
posera pas de problème, vu que "<Movie: %s>" ne contient que des
caratères ASCII. Par contre, si tu essaies d'utiliser autre chose,
genre u'ééééé', voilà ce qui se passera quand tu lanceras ton
programme:
File "toto.py", line 1
SyntaxError: Non-ASCII character 'xc3' in file toto.py on line 1, but
no encoding declared; see http://www.python.org/peps/pep-0263.html for
details
Ce qui se passe ici, c'est que tu as une chaîne unicode contenant des
caractères non-ASCII. Ces caractères sont encodés avec un certain
encodage dans ton fichier, décidé probablement par ton éditeur de code
source; mais Python n'a aucune idée de ce que c'est. Vu qu'essayer de
deviner n'est pas dans la philosophie du langage, il préfère s'arrêter
tout de suite et te renvoyer une erreur de syntaxe. La solution est
d'indiquer à Python l'encodage de tes fichiers sources à l'aide de la
ligne magique:
# -*- coding: … -*-
à placer en début de fichier. Bien sûr, remplacer les … par l'encodage
par défaut de ton éditeur préféré (que je ne connais pas, donc je ne
peux pas t'aider là-dessus). Et je te conseille la lecture de la page
citée dans l'erreur ci-dessus (http://www.python.org/peps/
pep-0263.html).

L'autre solution, c'est de passer à Python 3, et là toutes tes chaînes
seront des chaînes unicode par défaut et tu n'auras plus à tout
préfixer par des u partout. Mais ça ne changera rien à la nécessité de
déclarer ton encodage dans tes sources…

J'espère que c'est un peu plus clair.
- Eric -



NicolasP
Le #22322031
Si tu peux, essaie de changer de version de Python.
Il semblerait que ce problème soit apparu avec la 2.5.
A verifier.

Nicolas

Le 02/07/2010 13:40, NicolasP a écrit :
Le 02/07/2010 12:08, Laurent FRANCOIS a écrit :
tu as essayé :

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# j'ai mis utf-8 à la place de ...
# mon editeur "emacs 23"

class Movie(object):
def __init__(self, title):
self.title = title
def __repr__(self):
return u"<Movie: %s>" %(self.title)

Et ça marche?

Parce que chez moi ça ne marche pas.
Ni en script ni en interactif sur un terminal
ni en interactif avec PyCrust.



Et non, ça ne marche pas.
Il semblerait qu'il y ait un bug à ce niveau.
Tout se comporte comme si repr() retournait un type byte string mais avec un contenu Unicode.

Tu as 2 solutions :

1) print "%s" % uins

2) Encoder les chaines de caractères dans __repr__():
#!/usr/bin/env python
# -*- coding: UTF8 -*-
# j'ai mis utf-8 à la place de ...
# mon editeur "emacs 23"

import sys

class Movie(object):
def __init__(self, title):
self.title = title
def __repr__(self):
r = u"<Movie: %s>" %(self.title)
return r.encode(sys.stdout.encoding)

uins = Movie(u"ééééé")
print "%s" % uins
print Movie(u"ééééé")



Nicolas



Merci

Mon editeur emacs 23
le coding :

Coding system for saving this buffer:
Not set locally, use the default.
Default coding system (for new files):
U -- utf-8-unix (alias: mule-utf-8-unix)

Coding system for keyboard input:
= -- no-conversion (alias: binary)

Coding system for terminal output:
nil
Coding system for inter-client cut and paste:
nil
Defaults for subprocess I/O:
decoding: U -- utf-8-unix (alias: mule-utf-8-unix)

encoding: U -- utf-8-unix (alias: mule-utf-8-unix)


et
$locale

LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL >>
On 07/01/2010 07:58 PM, eb303 wrote:
On Jul 1, 8:08 am, Laurent FRANCOIS wrote:
Bonjour,

J'ai un probleme de charset

J'ai pas mal lu sur l'unicode et autre charset.
j'ai pas tout compris sinon je serais pas là pour
poser une question.

Voila mon probleme.

class Movie(object):
... def __init__(self, title):
... self.title = title
... def __repr__(self):
... return "<Movie: %s>" %(self.title)
...
>>> ins = Movie("ééééé")
>>> ins
<Movie: ééééé>
>>> uins = Movie(u"ééééé")
>>> uins
Traceback (most recent call last):
File "<stdin>", line 1, in<module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position
8-12: ordinal not in range(128)

>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>> sys.version
'2.5.5 (r255:77872, Apr 21 2010, 08:40:04) n[GCC 4.4.3]'



Assez simple en fait: quand tu demandes d'afficher uins, Python
appelle __repr__, qui fait "<Movie: %s>" %(self.title), et self.title
est une chaîne unicode. Vu que<Movie: %s>" n'en est pas une, Python
va essayer de représenter self.title en "byte string" pour pouvoir la
rentrer dans le %s, ce pour quoi il doit l'encoder. L'encodage par
défaut étant ASCII, il va faire en gros self.title.encode('ascii'), ce
qui évidemment ne fonctionne pas vu que self.title contient des
caractères accentués qui ne sont pas dans le jeu de caractère ASCII.
En fait, au final, Python fera:
u'ééééé'.encode('ascii')






Ce qui donne ce que tu as vu:
Traceback (most recent call last):
File "<stdin>", line 1, in<module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position
0-4: ordinal not in range(128)

Voilà pour le problème. Pour la solution, c'est une autre histoire, et
ça dépend de ce que tu veux faire en fait. La première chose serait de
passer toutes tes chaînes en chaînes unicode, et donc de modifier la
méthode __repr__ comme ça:
def __repr__(self):
return u"<Movie: %s>" %(self.title)
De cette façon, pas d'encodage quand self.title sera une chaîne
Unicode: elle rentre toute seule dans le %s. Dans ce cas précis, ça ne
posera pas de problème, vu que "<Movie: %s>" ne contient que des
caratères ASCII. Par contre, si tu essaies d'utiliser autre chose,
genre u'ééééé', voilà ce qui se passera quand tu lanceras ton
programme:
File "toto.py", line 1
SyntaxError: Non-ASCII character 'xc3' in file toto.py on line 1, but
no encoding declared; see http://www.python.org/peps/pep-0263.html for
details
Ce qui se passe ici, c'est que tu as une chaîne unicode contenant des
caractères non-ASCII. Ces caractères sont encodés avec un certain
encodage dans ton fichier, décidé probablement par ton éditeur de code
source; mais Python n'a aucune idée de ce que c'est. Vu qu'essayer de
deviner n'est pas dans la philosophie du langage, il préfère s'arrêter
tout de suite et te renvoyer une erreur de syntaxe. La solution est
d'indiquer à Python l'encodage de tes fichiers sources à l'aide de la
ligne magique:
# -*- coding: … -*-
à placer en début de fichier. Bien sûr, remplacer les … par l'encodage
par défaut de ton éditeur préféré (que je ne connais pas, donc je ne
peux pas t'aider là-dessus). Et je te conseille la lecture de la page
citée dans l'erreur ci-dessus (http://www.python.org/peps/
pep-0263.html).

L'autre solution, c'est de passer à Python 3, et là toutes tes chaînes
seront des chaînes unicode par défaut et tu n'auras plus à tout
préfixer par des u partout. Mais ça ne changera rien à la nécessité de
déclarer ton encodage dans tes sources…

J'espère que c'est un peu plus clair.
- Eric -






Publicité
Poster une réponse
Anonyme