Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

conversion de chaîne de caractères

11 réponses
Avatar
val
Bonjour,

Je suis en train de m'emmêler lamentablement les pinceaux sur un
problème de codage de string après avoir récupéré des données d'un
fichier excel avec win32com.client.

Dans une fonction j'ai ça :

rawtext=u''
val=xlWb.ActiveSheet.Cells(row,col).Value
rawtext=rawtext+repr(val.encode("iso-8859-1" ))
print rawtext

Et a un moment je l'écris dans un fichier :
save_file.write(rawtext)

Et je retrouve des caractères /xe9 et /xe8 à la place de é et è dans la
console et mon fichier.

Le contexte c'est python 2.6 sur XP
je ne sais pas si ça compte mais
un locale.getlocale() me donne (None, None)

Comment faire pour trouver quel est le code (standard?) du fichier xls
et le communiquer à python pour que les caractères s'inscrivent
correctement dans le fichier ?

10 réponses

1 2
Avatar
Francois Lafont
Bonjour,

Le 24/06/2011 13:19, val a écrit :

rawtext=u''
val=xlWb.ActiveSheet.Cells(row,col).Value



Quel est le type de val ? C'est un str ou un unicode. Il faudrait faire
un print type(val) pour le savoir. J'imagine que ça doit être un str et
si c'est le cas il faudrait connaître l'encodage. Je ne sais pas s'il y
ait un moyen de le connaître avec Python (je ne pense pas). On peut
imaginer que c'est l'encodage cp1252 car c'est l'encodage par défaut
sous Windows je crois.

rawtext=rawtext+repr(val.encode("iso-8859-1" ))



Cette ligne ne va pas je pense. Si on suppose que que val est de type
str encodé en cp1252, il faut faire :

rawtext = rawtext + val.decode('cp1252')
(comme ça on additionne de l'unicode avec de l'unicode.)

Et a un moment je l'écris dans un fichier :
save_file.write(rawtext)



Là non plus, ça ne va pas. Quand on utilise f.write(), il faut passer en
argument du str pas de l'unicode. L'unicode, c'est ce qu'il faut
manipuler dans le programme (car il n'y a pas de souci d'encodage
justement). En revanche, quand on veut lire ou écrire dans un fichier,
on manipule du str et c'est le programmeur qui doit connaître les
encodages. En gros, on m'avait expliqué ceci :

1) Quand on lit un fichier, on récupère du str et c'est à nous de
connaître l'encodage du texte qu'on récupère. Ça dépend de l'application
qui a créé les données. Sous Excel, comment sont encodées les chaînes
caractères ? Je l'ignore mais ça ne concerne plus Python.


2) On s'empresse de convertir le str en unicode via :

chaine_unicode = chaine_str.decode('encodage du str récupéré')

Puis on manipule du unicode uniquement.


3) Quand on veut écrire dans un fichier les chaines unicode qu'on a
manipulées dans 2), on utilise :

f.writre(chaine_unicode.encode('encodage'))

Et là on utilise l'encodage qu'on veut sauf si on veut lire les données
avec une application particulière qui utilise peut-être uniquement tel
ou tel encodage, mais là aussi c'est à nous de le savoir, ce n'est plus
un problème Python.

J'espère ne pas avoir trop dit de bêtises.


--
François Lafont
Avatar
Francois Lafont
Le 24/06/2011 13:47, Francois Lafont a écrit :

On peut
imaginer que c'est l'encodage cp1252 car c'est l'encodage par défaut
sous Windows je crois.



Après avoir fait une petite recherche rapide sur le Web, il semble bien
que ce soit ça. Donc je dirais qu'un truc dans le genre ci-dessous
devrait marcher :

rawtext = u''
val = xlWb.ActiveSheet.Cells(row,col).Value
rawtext = rawtext + val.decode('cp1252')

[etc...]

save_file.write(rawtext.encode('cp1252'))



--
François Lafont
Avatar
val
Francois Lafont a écrit le 24/06/2011 :
Le 24/06/2011 13:47, Francois Lafont a écrit :

On peut
imaginer que c'est l'encodage cp1252 car c'est l'encodage par défaut
sous Windows je crois.



Après avoir fait une petite recherche rapide sur le Web, il semble bien
que ce soit ça. Donc je dirais qu'un truc dans le genre ci-dessous
devrait marcher :

rawtext = u''
val = xlWb.ActiveSheet.Cells(row,col).Value
rawtext = rawtext + val.decode('cp1252')

[etc...]

save_file.write(rawtext.encode('cp1252'))



Merci pour la réponse.

rawtext=rawtext+val.decode('cp1252')
ou encore
rawtext=rawtext+val.decode('iso-8859-1')

Me donne une erreur unicodeEncodeError Ordinal not in range(128) dès
qu'une cellule contient un caractère accentué. Je ne comprends pas :
'é' est un caractère unicode, et il devrait bien avoir une
représentation valide en cp1252, non ?
Avatar
Francois Lafont
Le 24/06/2011 15:21, val a écrit :

Merci pour la réponse.

rawtext=rawtext+val.decode('cp1252')
ou encore
rawtext=rawtext+val.decode('iso-8859-1')

Me donne une erreur unicodeEncodeError Ordinal not in range(128) dès
qu'une cellule contient un caractère accentué.



Pourrais-tu fournir un ECM (Exemple Complet et Minimal) et donner le
message d'erreur tel quel ?


--
François Lafont
Avatar
Alain Ketterlin
val writes:

rawtext=rawtext+val.decode('cp1252')
ou encore
rawtext=rawtext+val.decode('iso-8859-1')

Me donne une erreur unicodeEncodeError Ordinal not in range(128) dès
qu'une cellule contient un caractère accentué.



Un vrai message d'erreur est toujours plus informatif. Le mieux est de
copier-coller ce que dit l'interpréteur.

François demandait à voir le résultat de "print type(val)", pourrais-tu
fournir cela ?

Il semble que la chaîne que tu récupères soit déjà en utf-8, mais il
faudrait le vérifier.

Je ne comprends pas : é' est un caractère unicode, et il devrai t bien
avoir une représentation valide en cp1252, non ?



Si la chaîne est en utf-8 et que tu demandes de la décoder comme si elle
était en iso-8859-1, tu vas avoir des surprises. C'est peut-être ce qui
t'arrive.

-- Alain.
Avatar
Michel Claveau - MVP
Bonsoir !

Si tu attaques Excel avec win32com.client, c'est que tu passes par COM.
Et COM retourne, pour les chaines, de l'Unicode. Donc, inutile de décoder
la valeur reçue.

Concentre-toi donc sur l'encodage dont tu as besoin.

Sinon, j'ai relevé :
- que tu uilises l'encodage sans paramètre de gestion d'erreur. Tu devrais
préciser 'ignore', plutôt que le 'strict' par défaut.
- la fonction repr() est inutile (c'est elle qui remplace les caractères
par ce que tu crois être des trucs bizarres).


Enfin, si tu utilises beaucoup, ou souvent, Excel depuis Python, j'avais
écris une classe toute prête. Mais on peut aussi préférer ré-inventer la
roue ; ce qui est souvent très instructif...
(http://www.ponx.org/download/CD/PONX/pxexcel.py)

@+
--
Michel Claveau
Avatar
val
Francois Lafont a écrit le 25/06/2011 :

Pourrais-tu fournir un ECM (Exemple Complet et Minimal) et donner le
message d'erreur tel quel ?



Désolé pour le retard, je n'étais pas là ce week-end...

J'ai essayé de faire un exemple minimal et ça donne ça :

_EMC.py :_
# -*- coding: iso-8859-1 -*-
#
# manipulation de chaînes
#
import sys

save_file=file('log.dat', 'w')
rawtext=u''
val=u'problème'
print type(val), val
rawtext=rawtext+val.encode('cp1252') # <-- c'est la ligne 11
try:
#print u
save_file.write(rawtext.encode('cp1252')+'n')
except:
print "xxxx", str(rawtext), sys.exc_info()
save_file.close()

le message complet d'erreur est le suivant :

F:pythontest>ECM.py
<type 'unicode'> problème
Traceback (most recent call last):
File "F:pythontestECM.py", line 11, in <module>
rawtext=rawtext+val.encode('cp1252')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 5:
ordinal not in range(128)

Je ne sais vraiment pas comment faire pour convertir et afficher le
unicode venant d'excel...
Avatar
Francois Lafont
Le 27/06/2011 10:39, val a écrit :

J'ai essayé de faire un exemple minimal et ça donne ça :



Je constate que finalement, dans ton ECM, il n'est même plus question
d'Excel.

_EMC.py :_
# -*- coding: iso-8859-1 -*-
#
# manipulation de chaînes
#
import sys

save_file=file('log.dat', 'w')
rawtext=u''
val=u'problème'
print type(val), val
rawtext=rawtext+val.encode('cp1252')



Normal que ça plante ici. val est de l'unicode et rawtext aussi. Ils
sont de même type. Donc il n'y a rien à faire à part simplement :

rawtext = rawtext + val

Je ne sais vraiment pas comment faire pour convertir et afficher le
unicode venant d'excel...



D'après Michel, ce que tu obtiens venant d'Excel est de l'unicode
directement donc tu n'as rien à convertir au départ. Tu fais juste bien
gaffe de manipuler ces chaînes unicode avec d'autres chaînes unicode
également c'est tout.

Le seul moment où il faudra convertir en str, c'est quand tu voudras
écrire dans un fichier :

save_file.write(chaine_unicode.encode('l'encodage-que-tu-souhaites'))



--
François Lafont
Avatar
Francois Lafont
Le 28/06/2011 01:00, Francois Lafont a écrit :

rawtext=rawtext+val.encode('cp1252')



Normal que ça plante ici. val est de l'unicode et rawtext aussi. Ils
sont de même type. Donc il n'y a rien à faire à part simplement :

rawtext = rawtext + val



Pour être précis, le val.encode('cp1252') n'a aucun sens pour moi car
rawtext est de l'unicode et val aussi donc on peut/doit les additionner
directement. C'est ça qu'il faut retenir.

Ceci étant dit, ce n'est pas le val.encode('cp1252') qui provoque une
erreur ici. L'instruction val.encode('cp1252') toute seule est
parfaitement licite et elle renvoie un str encodé en cp1252. Mais comme
tu additionnes un unicode (rawtext) avec un str (val.encode('cp1252')),
il va chercher à convertir le str en unicode et en fait :

ton « rawtext = rawtext + val.encode('cp1252') » revient en fait à ça :

rawtext = rawtext + val.encode('cp1252').decode('ascii')

(conversion implicite du str en unicode, mais par défaut Python part du
principe que le str est en ascii.)

Et là boum ! Erreur puisque que le str val.encode('cp1252') n'est pas
100% ASCII.


--
François Lafont
Avatar
val
Michel Claveau - MVP a écrit le 26/06/2011 :
Bonsoir !

Si tu attaques Excel avec win32com.client, c'est que tu passes par COM.
Et COM retourne, pour les chaines, de l'Unicode. Donc, inutile de décoder
la valeur reçue.

Concentre-toi donc sur l'encodage dont tu as besoin.

Sinon, j'ai relevé :
- que tu uilises l'encodage sans paramètre de gestion d'erreur. Tu devrais
préciser 'ignore', plutôt que le 'strict' par défaut.
- la fonction repr() est inutile (c'est elle qui remplace les caractères
par ce que tu crois être des trucs bizarres).


Enfin, si tu utilises beaucoup, ou souvent, Excel depuis Python, j'avais
écris une classe toute prête. Mais on peut aussi préférer ré-inventer la
roue ; ce qui est souvent très instructif...
(http://www.ponx.org/download/CD/PONX/pxexcel.py)

@+



En fait je vous ai déja 'piqué' votre script car je suis parti de :

http://www.velocityreviews.com/forums/t352440-how-to-read-excel-files-in-python.html

Merci.
1 2