Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 21/03/2009, à 02:20

wlourf

script python : paramètres et accents...

Bonjour,

Avec python 2.6, lors d'un saise avec des accents par raw_input, je peux afficher la valeur saisie après l'avoir décodé avec valeur.decode(sys.stdin.encoding,"strict"), que ce soit avec windows ou avec ubuntu.

Par contre quand je passe un paramètre accentué au script, je n'arrive pas à afficher  ce paramètre correctement avec decode(sys.stdin.encoding,"strict") : dédé.txt devient dùdù.txt, ceci seulement sous windows

Avec ça : print fichier.decode("latin-1"), ça fonctionne mais ça ne me semble pas très portable, en plus ça ne fonctionne plus sous ubuntu, forcément!

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import sys,os
from optparse import OptionParser

parser = OptionParser(usage="usage blabla",version="%prog 22")
(options, args) = parser.parse_args()

fichier=args[0]

print fichier #nok
print fichier.decode(sys.stdin.encoding,"strict")#nok
print fichier.decode("latin-1") #--ok--

f=open(fichier)
print f.read()

Si quelqu'un  a une idée ... même si de loin ça ressemble plus à un problème windows tongue (je peux interdire les accents juste pour les utilisateurs de windows mais ce ne serait pas très fairplay!)

Hors ligne

#2 Le 21/03/2009, à 21:59

zerevo

Re : script python : paramètres et accents...

Désolé je peux pas t'aider j'ai pas windows tongue

Hors ligne

#3 Le 21/03/2009, à 22:06

Kanor

Re : script python : paramètres et accents...

Ou tu fais un code spécefique pour les utilisateur de windows si je me trompe pas il y a une varaible pour savoir l'os qui tourne

Hors ligne

#4 Le 21/03/2009, à 22:31

HP

Re : script python : paramètres et accents...

platform ou os.uname (au choix)…
perso, j'ai tendance à privilégier uname parce que c'est difficile de ne pas utiliser import os ! tongue


cat /dev/urandom >/dev/null 2>&1 #github

Hors ligne

#5 Le 21/03/2009, à 23:34

wlourf

Re : script python : paramètres et accents...

ok, merci, je connaissais sys.name ou os.platform qui retournent chacun 6 ou 7 valeurs (pour os.name 'posix', 'nt', 'mac', 'os2', 'ce', 'java', 'riscos'), dans l'absolu, ça ferait 6 ou 7 tests à effectuer mais ça m'étonnerai que mon petit script soit utilisé ailleurs que sur windows ou linux.

Mais pour une même platforme l'encodage de la console peut être modifié par l'utilisateur, c'est pour ça que j'utilise sys.stdout.encoding pour récupérer l'encodage de le console ou tourne le script. Comme je ne suis pas sûr d'avoir bien compris la doc http://docs.python.org/library/sys.html#sys.stdin j'essaierai avec stderr ou stdout mais je ne crois pas que ça changera beaucoup.

Sinon moi aussi je n'ai pas windows (sauf au boulot) mais je ne suis pas sectaire et peut passer des scripts aux windoziens!

Hors ligne

#6 Le 22/03/2009, à 00:41

zerevo

Re : script python : paramètres et accents...

python probleme.py àéèÖôûÜÛîIFSDFD
àéèÖôûÜÛîIFSDFD
àéèÖôûÜÛîIFSDFD
àéèÖôûÜÛîIFSDFD

Tu as mis le 2eme à nok et le 3eme à ok alors que chez moi j'ai le 2eme qui fonctionne et pas le 3eme.
Mon pc est sous Ubuntu 9.04 et j'ai LANG=fr_FR.UTF-8

Hors ligne

#7 Le 22/03/2009, à 09:58

HP

Re : script python : paramètres et accents...

zerevo a écrit :

Tu as mis le 2eme à nok et le 3eme à ok alors que chez moi j'ai le 2eme qui fonctionne et pas le 3eme.

Évidemment… chez moi aussi wink.

wlourf a écrit :

ok, merci, je connaissais sys.name ou os.platform qui retournent chacun 6 ou 7 valeurs (pour os.name 'posix', 'nt', 'mac', 'os2', 'ce', 'java', 'riscos') […] ça ferait 6 ou 7 tests à effectuer […]

Je répondais juste à Kanor… je n'ai jamais prétendu que c'était LA solution à tes soucis d'encodage tongue.

mais de toute façon si le seul but était de détecter un Windows, ça ne ferait pas 6 tests à effectuer.
Faudra aussi que tu me dises d'où tu sors sys.name et os.platform tongue, désolé moi je ne connais pas…

D'ailleurs os.name je me demande quand est ce qu'il sort 'mac' parce que là sous Mac il me sort 'posix' (ce qui me semble correct… ça dépend ce qu'on attend de cette info ! lol

Dernière modification par HP (Le 22/03/2009, à 10:08)


cat /dev/urandom >/dev/null 2>&1 #github

Hors ligne

#8 Le 22/03/2009, à 11:26

aleph2

Re : script python : paramètres et accents...

> wlourf

Je ne voudrais pas ébranler tes certitudes, mais ce type de problème est aussi ennuyeux sous *les* Linux que sous *les* Windows.

Le problème de base est le suivant: quelle est le codage de sys.argv ? Il se trouve que sous les Linux, celui-ci dépend des "locale" et que sous les Windows, celui-ci dépend de Windows.

A cela s'ajoute aussi le fait que si un des arguments est un *nom* de fichier, il faut aussi tenir compte de la façon dont celui-ci est codé sur le périphérique qui le contient. (par, ex. CP_ACP connu sous le nom "mbcs" par Python pour une partition fat32, clef usb, ...)

Google > python sys.argv encoding ne manque pas d'informations.

Mon commentaire. Comme la majorité des gens ne comprend rien à rien à tout ce qui touche le codage des caractères, toujours prendre avec des pincettes ce que l'on y trouve.

#9 Le 22/03/2009, à 12:15

HP

Re : script python : paramètres et accents...

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import sys

charset = 'iso-8859-1'

for i in range(len(sys.argv)):
    sys.argv[i] = sys.argv[i].decode(sys.stdin.encoding, 'replace').encode(charset, 'replace') 
    print('in:  %s' % sys.argv[i])
    print('out: %s' % sys.argv[i].decode(charset).encode(sys.stdout.encoding))

if 'àéèÖôûÜÛîIFSDFD' in sys.argv:
    result = 'on a bien trouvé %(tofind)s dans les arguments' % {'tofind' : '`àéèÖôûÜÛîIFSDFD`'}
    print(result.decode(charset).encode(sys.stdout.encoding))
python test.py àéèÖôûÜÛîIFSDFD à߬µπ
in:  test.py
out: test.py
in:  ?????????IFSDFD
out: àéèÖôûÜÛîIFSDFD
in:  ?߬??
out: à߬µ?
on a bien trouvé `àéèÖôûÜÛîIFSDFD` dans les arguments

Voilà quoi… wink


cat /dev/urandom >/dev/null 2>&1 #github

Hors ligne

#10 Le 22/03/2009, à 16:46

aleph2

Re : script python : paramètres et accents...

> hp

Le principe de travail est correct ou "n'est pas faux". Tu décodes les arguments en créant un unicode pivot que tu réencodes en iso-8859-1.

Mais...

...la difficulté qui peut survenir vient du fait que, selon les plateformes et/ou leurs configurations et/ou la configuration de Python sous ces plateformes, le codage d'entrée de Python (sys.stdin.encoding) ne correspond pas nécessairement au codage des arguments (sys.argv) de la plateforme, sans compter que le codage des arguments peut être différent du codage du système de fichiers.

Bref, un cas où l'ascii, lingua franca de l'informatique, rend bien service.

#11 Le 22/03/2009, à 16:58

HP

Re : script python : paramètres et accents...

aleph2 a écrit :

sans compter que le codage des arguments peut être différent du codage du système de fichiers

Je suis d'accord, et je ne le traitais pas ici… puis faudra que notre ami bosse un peu !

aleph2 a écrit :

le codage d'entrée de Python (sys.stdin.encoding) ne correspond pas nécessairement au codage des arguments (sys.argv) de la plateforme

çà c'est un peu plus bizarre ! yikes


cat /dev/urandom >/dev/null 2>&1 #github

Hors ligne

#12 Le 22/03/2009, à 18:00

aleph2

Re : script python : paramètres et accents...

> HP

>çà c'est un peu plus bizarre !

Oui. Sous Windows le problème est patent. Je l'ai remarqué hier en effectuant quelques petits tests pour essayer de répondre correctement à wlourf. Sous Windows, en mode console, DOS box, sys.stdin.encoding est cp850 (Py25, 26, 30), ce qui est correct, et pose visiblement problème pour décoder sys.argv, alors que cela fonctionne en utilisant iso-8859-1 (?). J'ai été surpris de ce dysfonctionnement et il me semble que ce n'était pas le cas "auparavant" (version ???). D'un autre côté, ceci est en tel serpent de mer (v. forum des développeurs) que je n'en ai pas été plus étonné que tant.

Sous Linux les choses devraient être plus "propres", bien que, en cherchant sur la toile, on découvre aussi quelques surprises.

#13 Le 02/05/2009, à 16:15

NicDumZ

Re : script python : paramètres et accents...

HP a écrit :
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import sys

charset = 'iso-8859-1'

for i in range(len(sys.argv)):
    sys.argv[i] = sys.argv[i].decode(sys.stdin.encoding, 'replace').encode(charset, 'replace') 
    print('in:  %s' % sys.argv[i])
    print('out: %s' % sys.argv[i].decode(charset).encode(sys.stdout.encoding))

if 'àéèÖôûÜÛîIFSDFD' in sys.argv:
    result = 'on a bien trouvé %(tofind)s dans les arguments' % {'tofind' : '`àéèÖôûÜÛîIFSDFD`'}
    print(result.decode(charset).encode(sys.stdout.encoding))

[snip]

Voilà quoi… wink

Pourquoi forcément réencoder dans un charset intermédiaire? L'unicode est justement fait comme format de données pivot, pour ne pas avoir à se trainer un charset intermédiaire "temporaire"

#!/usr/bin/env python

import sys

for i in range(len(sys.argv)):
    sys.argv[i] = sys.argv[i].decode(sys.stdin.encoding, 'replace') # type(sys.argv[i]) == unicode
    print(u'in:  %s' % sys.argv[i]) # print u' ' pour de l'unicode
    print('out: %s' % sys.argv[i].encode(sys.stdout.encoding))

Ce code fait la même chose.

En plus, utiliser un charset intermédiaire pose problème. Dans ton exemple, tu utilises un encodage intermédiaire européen: c'est bien ça fonctionnera pour les caractères accentués occidentaux, quel que soit la locale qu'utilise ton utilisateur.

Cependant, si ton utilisateur est un chinois, ou un Japonais, le fait de réencoder en iso-8859-1 une chaine entrée, disons, en shift-jis ( 'sjis', encodage japonais), lèvera une Erreur:

# "konichiwa", encodé en shift-jis. 
hello = '\x82\xb1\x82\xf1\x82\xc9\x82\xbf\x82\xcd' 
# Pour obtenir cette chaine, on aurait aussi bien faire:
# hello = u'こんにちは'.encode('sjis')
# (mais j'imagine que tout le monde n'a pas le support du jap' ici =) )

# Cette chaîne arrive en argument, l'encodage systeme de l'utilisateur est 'sjis'
# on essaie donc de reproduire sys.argv[i].decode(sys.stdin.encoding, 'replace').encode(charset, 'replace') :
en_unicode = hello.decode('sjis') # sys.argv[i].decode(sys.stdin.encoding), OK
en_latin1 = hello.encode('iso-8859-1') #NOK, lève UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-4: ordinal not in range(256)

#Du coup, l'option 'replace' est utilisée, pour ignorer les caractères non encodables en latin1 :
en_latin1 = hello.encode('iso-8859-1', 'replace')
print en_latin1 # Affiche 5 points d'interrogation, au lieu des 5 caractères jap'

Pour résumer, utiliser un encodage intermédiaire plutot que l'unicode, c'est se fermer des possibilités. Plus les différences entre ta variable locale 'charset' et sys.stdin.encoding seront grandes, moins ton texte final ressemblera à ce que l'utilisateur a entré. Il faut donc autant que possible, utiliser de l'unicode en interne.

Hors ligne