OVH Cloud OVH Cloud

Python et les accents

32 réponses
Avatar
nico
Bonjour,

Lorsque je mets des accents dans mes chaines de caractères, j'ai un warning généré par python. Normal.
J'aimerais supprimer ce warning mais je n'y arrive pas.
Je suis sous windows. J'utilise Eclipse 3.1 avec le plug-in PyDev.
Je mets le commentaire qui va bien au début de mon fichier pour dire que j'ai des caractères de type UTF-8. J'enregistre mon fichier au format UTF-8 (ou du moins je pense que c'est le cas). J'ai bien mes caractères accentués dans le fichier source mais à l'exécution j'ai 2 caractères bizarres à chaque lettre accentuée. Je suppose que ces deux caractères correspondent au code UTF-8 non "décodé". Ce qui est étrange c'est que dès que je mets le commentaire de type d'encodage au début du fichier, Eclipse sauvegarde automatiquement le fichier dans le nouvel encodage. Comme si Eclipse connaissait cette "instruction". Peut-être que c'est PyDev qui fait ça ?
Quelqu'un a t-il déjà eu ce genre problème ? Et éventuellement une solution ?

Nicolas

10 réponses

1 2 3 4
Avatar
noone
$ man file


FILE(1)
Copyrighted but distributable
FILE(1)

NAME
file - determine file type

SYNOPSIS
file [ -bcikLnNprsvz ] [ -f namefile ] [ -F separator ] [ -m
magicfiles ] file ...
file -C [ -m magicfile ]

DESCRIPTION
This manual page documents version 4.12 of the file command.

File tests each argument in an attempt to classify it.
There are three sets of tests, performed in this order: filesystem
tests, magic number
tests, and language tests. The first test that succeeds causes
the file type to be printed.

The type printed will usually contain one of the words text (the
file contains only printing characters and a few common control
characters and is
probably safe to read on an ASCII terminal), executable (the
file contains the result of compiling a program in a form understandable
to some UNIX
kernel or another), or data meaning anything else (data is
usually ‘binary’ or non-printable). Exceptions are well-known file
formats (core files,
tar archives) that are known to contain binary data. When
adding local definitions to /etc/magic, preserve these keywords. People
depend on know‐
ing that all the readable files in a directory have the word
‘‘text’’ printed. Don’t do as Berkeley did and change ‘‘shell
commands text’’ to
‘‘shell script’’. Note that the file /usr/share/misc/file/magic
is built mechanically from a large number of small files in the
subdirectory Magdir
in the source distribution of this program.

The filesystem tests are based on examining the return from a
stat(2) system call. The program checks to see if the file is empty, or
if it’s some
sort of special file. Any known file types appropriate to the
system you are running on (sockets, symbolic links, or named pipes
(FIFOs) on those
systems that implement them) are intuited if they are defined in
the system header file <sys/stat.h>.

The magic number tests are used to check for files with data in
particular fixed formats. The canonical example of this is a binary
executable
(compiled program) a.out file, whose format is defined in
a.out.h and possibly exec.h in the standard include directory. These
files have a ‘magic
number’ stored in a particular place near the beginning of the
file that tells the UNIX operating system that the file is a binary
executable, and
which of several types thereof. The concept of ‘magic number’
has been applied by extension to data files. Any file with some
invariant identifier
at a small fixed offset into the file can usually be described in
this way. The information identifying these files is read from
/etc/magic and the
compiled magic file /usr/share/misc/file/magic.mgc , or
/usr/share/misc/file/magic if the compile file does not exist.

If a file does not match any of the entries in the magic
file, it is examined to see if it seems to be a text file. ASCII,
ISO-8859-x, non-ISO
8-bit extended-ASCII character sets (such as those used on
Macintosh and IBM PC systems), UTF-8-encoded Unicode, UTF-16-encoded
Unicode, and EBCDIC
character sets can be distinguished by the different ranges and
sequences of bytes that constitute printable text in each set. If a
file passes any
of these tests, its character set is reported. ASCII,
ISO-8859-x, UTF-8, and extended-ASCII files are identified as ‘‘text’’
because they will be
mostly readable on nearly any terminal; UTF-16 and EBCDIC are
only ‘‘character data’’ because, while they contain text, it is text
that will require
translation before it can be read. In addition, file will
attempt to determine other characteristics of text-type files. If the
lines of a file
are terminated by CR, CRLF, or NEL, instead of the
Unix-standard LF, this will be reported. Files that contain embedded
escape sequences or over‐
striking will also be identified.

Once file has determined the character set used in a text-type
file, it will attempt to determine in what language the file is
written. The lan‐
guage tests look for particular strings (cf names.h) that can
appear anywhere in the first few blocks of a file. For example, the
keyword .br indi‐
cates that the file is most likely a troff(1) input file, just as
the keyword struct indicates a C program. These tests are less reliable
than the
previous two groups, so they are performed last. The language
test routines also test for some miscellany (such as tar(1) archives).

Any file that cannot be identified as having been written in any
of the character sets listed above is simply said to be ‘‘data’’.






Pour plus d'information sur la manière dont ça marche le mieux est de
regarder le source (en C)

apt-get source file

si on a une Debian ou assimilée


ou en regardant dans le répertoire des sources d'une distrib Linux :
Ubuntu au pif

http://fr.archive.ubuntu.com/ubuntu/pool/main/f/file/

Désolé de ne pas pouvoir en dire plus

ce que je sais c'est que chez moi ça reconnais la différence entre de
utf-8 et de l'iso-8859-1 et ça c'est déjà bien pratique
Avatar
Do Re Mi chel La Si Do
Bonsoir !


...ça reconnait la différence entre de utf-8 et de l'iso-8859-1




A condition que le fichier UTF-8 ait été enregistré sous une forme
respectueuse (cf les 4 premiers octets). Ce qui doit être le cas le plus
fréquent. En fait, lorsqu'un éditeur ouvre un fichier, il utilise les même
techniques, que ce soit sous Linux, ou sous Windows, pour déterminer le
format du fichier.

Il me semble d'ailleurs me rappeler qu'il y avait un exemple, dans le Python
Cookbook (1ère version).

Conclusion : c'est kif-kif partout. Match nul intégral.


@-salutations

Michel Claveau



Avatar
nico
Bonjour !


Je suis d'accord : les deux caractères correspondent bien à de l'UTF-8
"non-décodés" ; disons traités comme de l'ANSI ou de l'ASCII brut.

Ce qu'il faut, c'est que ta sortie traite l'UTF-8. Alors, question : comment
visualises-tu le résultat de tes scripts ?

Si c'est la console, problème, elle ne gère pas l'UTF-8 ; il faut alors
revenir au cp1252, utiliser la commande "CHCP 1252" pour dire à la console
de se mettre en cp1252, et, éventuellement, changer la police, dans les
propriétés de la console.

Si tu utilises une console virtuelle (par exemple avec SCite), il faut
vérifier ses paramètres, et la police de caractères utilisée. Je conseille
Arial Unicode, qui peut représenter plus de 56 000 caractères unicode.

Si tu utilises un GUI (wx, tk, etc.), il faut vérifier que tu utilises bien
une version unicode.

Si tu utilises les API de windows, (avec ctypes ou pywin32), il suffit de
choisir les version unicode, et il ne devrait pas y avoir de problème.


Perso, je travaille en cp1252 pour tout ce qui console, et en UTF-8 pour les
gros script, à cause d'un bug de Python 2.4 et 2.4.1 (sur les grandes lignes
en cp1252). Alors, dans le cas de l'UTF-8 en console, je convertis la sortie
en cp1252 (1).


J'espère que ces indications aideront...



@-salutations

Michel Claveau




(1) en fait, je n'utilise pas que cp1252, mais aussi cp1251 (Russie), cp1250
(Europe centrale), et cp1253 (Grèce), selon les besoins. Tous fonctionnent
bien sous windows.





Bon, après un peu plus d'investigations, il s'avère que j'avais oublié de déclarer les chaines concernées en unicode (pas mis le 'u' devant la chaine). Quand je suis passé de ASCII (qui génère des warnings) à UTF-8, j'ai changé l'encodage du fichier. Je pensais que toutes les chaines de caractères seraient codées en unicode et interprétées comme telles. Mais c'était une erreur. Apparemment, toutes les chaines de caractères sont codées unicode (utf-8) de part le format du fichier. Mais si l'on ne spécifie pas à Python qu'il s'agit d'une chaine unicode, elle est interprétée en ASCII. D'où les deux caractères bizarres à la place d'une lettre accentuée.
Par contre, wxPython version ANSI ou unicode, ça ne change rien au comportement. Ou alors, j'ai encore raté quelquechose.

Mais pourquoi utiliser tous ces encodages au lieu d'un seul et unique ?
UTF-8 n'est-il pas universel ?

Merci pour les précisions.

Nicolas

Avatar
Laurent Pointal
nico wrote:

Mais pourquoi utiliser tous ces encodages au lieu d'un seul et unique ?
UTF-8 n'est-il pas universel ?


L'histoire... unicode est arrivé un peu tard et d'autres solutions
alternatives ont vu jour. Faut quand même se souvenir qu'à une époque on
comptait les octets...

http://en.wikipedia.org/wiki/Character_encoding
http://lib.ua.ac.be/KB/pn/pnoerr1.html
http://tronweb.super-nova.co.jp/characcodehist.html

M'enfin, le nombre de choses qu'on se traine parce que ça a existé un
jour (et d'ailleurs quand on n'est plus capable de le supporter, ça fout
certaines personnes dans la m**** - genre plus capable de relire ses
vieilles disquettes).


A+

Laurent.

Avatar
Laurent Pointal
Pour l'historique des accents, cette page introduit les premiers encodages:
http://homepages.cwi.nl/~dik/english/codes/stand.html
Il donne les tables, ainsi que quelques commentaires sur comment/pourquoi.

Quand on lit:
<quote>
This is the original version of EBCDIC, IBM's own standard. Although it
has been claimed that it predates ASCII, that is not true, this standard
dates from 1964. Strange enough, IBM cooperated in the creation of
ASCII, but did not implement it. The main concern was cost of
translation of card columns to internal code which they thought should
be done entirely in hardware, something other manufacturers had already
abandoned.
</quote>

On voit que les problèmes de ressources n'étaient pas négligeables...
"cost of translation of card columns ".
Avatar
Hervé Cauwelier
Je pensais que toutes les chaines de
caractères seraient codées en unicode et interprétées comme telles. Mais
c'était une erreur. Apparemment, toutes les chaines de caractères sont
codées unicode (utf-8) de part le format du fichier.


Non ces chaînes ne sont pas codées en unicode, c'est contradictoire. Ce
que tu vois à l'écran est forcément une représentation dans un codec, et
c'est ce codec que tu dois déclarer à Python. Unicode est la
classification des caractères/glyphes/vecteurs et autres termes mais pas
leur codage. Pour ça il y a UTF-7 (les caractères du genre +XXXX), UTF-8
(qui prend de un à plusieurs octets), UTF-16 et UTF-32 en variantes
petit boutiste et grand boutiste.

Il faut bien lire le lien que j'ai donné dans le message précédent.

Non Encolpe, on n'est pas pressé de passer à UTF-32...

--
Hervé Cauwelier
http://www.oursours.net/

Avatar
nico

L'histoire... unicode est arrivé un peu tard et d'autres solutions
alternatives ont vu jour. Faut quand même se souvenir qu'à une époque on
comptait les octets...



J'ai l'habitude de compter les octets (1K de RAM en tout en pour tout, je connais bien). C'est même ma spécialité. Et tout ce que je connaissais jusqu'à maintenant c'était le bon vieil ASCII de base.
Je ne pensais pas que des accents pouvaient mettre un foutoir pareil sur une plateforme comme Windows. Je pensais que ce genre de problème était résolu depuis longtemps.

Nicolas

Avatar
bruno modulix
Do Re Mi chel La Si Do wrote:

...ça reconnait la différence entre de utf-8 et de l'iso-8859-1




A condition que le fichier UTF-8 ait été enregistré sous une forme
respectueuse (cf les 4 premiers octets).


Le Byte Order Mark sert à l'origine - et comme son nom l'indique - à
préciser l'ordre des bytes quand l'encodage se fait sur plus d'un byte
(-> utf-16 et plus) - il n'y a pas lieu de préciser si on est en big ou
little endian pour un encodage sur un byte. L'ajout systématique d'un
"BOM" (qui n'en n'est en fait pas un...) au début des fichiers encodés
en UTF-8 est une spécialité MS Windows - et peut s'avérer une parfaite
nuisance sur d'autres systèmes. Bref, ce n'est en rien une "forme
respectueuse" en ce qui concerne l'UTF-8.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"




Avatar
nico

Je pensais que toutes les chaines de caractères seraient codées en
unicode et interprétées comme telles. Mais c'était une erreur.
Apparemment, toutes les chaines de caractères sont codées unicode
(utf-8) de part le format du fichier.



Non ces chaînes ne sont pas codées en unicode, c'est contradictoire. Ce
que tu vois à l'écran est forcément une représentation dans un codec, et
c'est ce codec que tu dois déclarer à Python. Unicode est la
classification des caractères/glyphes/vecteurs et autres termes mais pas
leur codage. Pour ça il y a UTF-7 (les caractères du genre +XXXX), UTF-8
(qui prend de un à plusieurs octets), UTF-16 et UTF-32 en variantes
petit boutiste et grand boutiste.

Il faut bien lire le lien que j'ai donné dans le message précédent.

Non Encolpe, on n'est pas pressé de passer à UTF-32...



J'ai bien lu l'article. Il est très intéressant et confirme bien l'idée que je me faisais de l'unicode et des encodages. Mis à part que comme beaucoup, je pensais qu'unicode définissait au maximum 65536 caractères (ou points de codes).
Je reviens quand même sur mon fichier. Je le déclare comme étant encodé en utf-8 et je l'enregistre au format utf-8. Donc, quand je mets un caractère "é" il doit être codé comme tel dans mon fichier où qu'il soit. Qu'il soit dans un commentaire, dans une chaine de caractères ou dans une variable (je sais, on n'a pas le droit mais c'est pour l'explication), il doit être codé de la même façon dans mon fichier. Donc Python devrait connaître ce caractère comme un "é" où qu'il soit dans mon fichier. Alors pourquoi ce caractère "é" s'affiche mal lorsque je le mets dans une chaine de caractère alors qu'il s'affiche bien lorsque je le mets dans une chaine de caractère unicode ? Ca voudrais dire que Python interprète le contenu d'une chaine de caractère comme étant de l'ASCII quelquesoit le codage du fichier. On n'est pas loin du bug là. Non ?

Nicolas


Avatar
Laurent Pointal
nico wrote:
Je reviens quand même sur mon fichier. Je le déclare comme étant encodé
en utf-8 et je l'enregistre au format utf-8. Donc, quand je mets un
caractère "é" il doit être codé comme tel dans mon fichier où qu'il
soit. Qu'il soit dans un commentaire, dans une chaine de caractères ou
dans une variable (je sais, on n'a pas le droit mais c'est pour
l'explication), il doit être codé de la même façon dans mon fichier.
Donc Python devrait connaître ce caractère comme un "é" où qu'il soit
dans mon fichier. Alors pourquoi ce caractère "é" s'affiche mal lorsque
je le mets dans une chaine de caractère alors qu'il s'affiche bien
lorsque je le mets dans une chaine de caractère unicode ? Ca voudrais
dire que Python interprète le contenu d'une chaine de caractère comme
étant de l'ASCII quelquesoit le codage du fichier. On n'est pas loin du
bug là. Non ?

Nicolas


C'est ça (relis un de mes posts précédents "Qu'est-ce qu'une chaine
classique").

u"Hébé" ==> Python prend l'encodage du fichier et crée une chaine
Unicode avec les caractères qui vont bien.

"Héhé" ==> Python crée une chaine 'classique', c'est à dire un flot
d'octets sans attribut d'encodage spécifique, en recopiant bêtement les
octets des caractères entre les quotes. S'il a besoin de convertir cette
chaîne dans un autre encodage, il considère que cette chaîne est en
sys.getdefaultencoding(), donc généralement de l'ASCII, et s'il y a des
caractères parasites (é) il n'aime pas.

Mais ce n'est pas un bug. Si tu veux des accents les chaînes Unicode
sont la (meilleure) solution.

A+

Laurent.

Note: J'ai mis du temps à le comprendre, mais une fois qu'on le sait,
tout paraît (presque) simple.

1 2 3 4