122 votes

Pourquoi déclarer l'unicode par chaîne en python ?

Je suis encore en train d'apprendre python et j'ai un doute :

Dans python 2.6.x, je déclare généralement l'encodage dans l'en-tête du fichier comme ceci (comme dans PEP 0263 )

# -*- coding: utf-8 -*-

Après cela, mes cordes sont écrites comme d'habitude :

a = "A normal string without declared Unicode"

Mais à chaque fois que je vois le code d'un projet python, l'encodage n'est pas déclaré dans l'en-tête. Au lieu de cela, il est déclaré à chaque chaîne de caractères comme ceci :

a = u"A string with declared Unicode"

Quelle est la différence ? À quoi cela sert-il ? Je sais que Python 2.6.x définit l'encodage ASCII par défaut, mais il peut être remplacé par la déclaration de l'en-tête, alors quel est l'intérêt de chaque déclaration de chaîne ?

Addendum : Il semble que j'ai confondu l'encodage des fichiers avec celui des chaînes de caractères. Merci de l'explication :)

6 votes

# coding: utf8 est suffisant, pas besoin de -*-

1 votes

@jellyfish Je suppose que vous vouliez taper # coding: utf-8 .

0 votes

Devrait être #coding=utf-8 . python.org/dev/peps/pep-0263

167voto

Chris B. Points 14211

Ce sont deux choses différentes, comme d'autres l'ont mentionné.

Lorsque vous spécifiez # -*- coding: utf-8 -*- vous dites à Python que le fichier source que vous avez sauvegardé est utf-8 . La valeur par défaut pour Python 2 est ASCII (pour Python 3 c'est utf-8 ). Cela affecte simplement la façon dont l'interpréteur lit les caractères dans le fichier.

En général, ce n'est probablement pas la meilleure idée d'intégrer des caractères unicode élevés dans votre fichier, quel que soit l'encodage. Vous pouvez utiliser des échappatoires de chaîne unicode, qui fonctionnent dans les deux encodages.


Lorsque vous déclarez une chaîne de caractères avec un u en tête comme u'This is a string' il indique au compilateur Python que la chaîne est en Unicode et non en octets. Ceci est géré de manière transparente par l'interpréteur ; la différence la plus évidente est que vous pouvez maintenant intégrer des caractères Unicode dans la chaîne (c'est-à-dire, u'\u2665' est désormais légal). Vous pouvez utiliser from __future__ import unicode_literals pour qu'elle devienne la valeur par défaut.

Ceci ne s'applique qu'à Python 2 ; dans Python 3, la valeur par défaut est Unicode, et vous devez spécifier une valeur de b devant (comme b'These are bytes' pour déclarer une séquence d'octets).

0 votes

Merci pour l'explication ! Je vais l'accepter car c'est la plus complète :)

2 votes

Le codage par défaut des sources pour Python 2 est le suivant ascii .

28 votes

C'est en fait une excellente idée d'intégrer des caractères unicode élevés dans votre fichier. Je doute que les non-anglophones veuillent lire des échappements unicode dans leurs chaînes de caractères.

23voto

Mark Tolonen Points 32702

Comme d'autres l'ont dit, # coding: spécifie l'encodage dans lequel le fichier source est enregistré. Voici quelques exemples pour illustrer cela :

Un fichier enregistré sur le disque en tant que cp437 (mon encodage de console), mais aucun encodage déclaré

b = 'über'
u = u'über'
print b,repr(b)
print u,repr(u)

Sortie :

  File "C:\ex.py", line 1
SyntaxError: Non-ASCII character '\x81' in file C:\ex.py on line 1, but no
encoding declared; see http://www.python.org/peps/pep-0263.html for details

Sortie du fichier avec # coding: cp437 ajouté :

über '\x81ber'
über u'\xfcber'

Au début, Python ne connaissait pas l'encodage et se plaignait du caractère non-ASCII. Une fois qu'il connaissait l'encodage, la chaîne d'octets obtenait les octets qui se trouvaient réellement sur le disque. Pour la chaîne Unicode, Python a lu \x81 Je savais que dans le CP437, c'était une ü et l'a décodé dans le codepoint Unicode pour ü qui est U+00FC. Lorsque la chaîne d'octets a été imprimée, Python a envoyé la valeur hexadécimale 81 à la console directement. Lorsque la chaîne Unicode a été imprimée, Python a correctement détecté mon encodage de console comme étant cp437 et a traduit Unicode ü à la valeur cp437 pour ü .

Voici ce qui se passe avec un fichier déclaré et enregistré en UTF-8 :

ber '\xc3\xbcber'
über u'\xfcber'

En UTF-8, ü est codé sous forme d'octets hexadécimaux C3 BC La chaîne d'octets contient donc ces octets, mais la chaîne Unicode est identique à celle du premier exemple. Python a lu les deux octets et les a décodés correctement. Python a imprimé la chaîne d'octets de manière incorrecte, car il a envoyé les deux octets UTF-8 représentant ü directement sur ma console cp437.

Ici le fichier est déclaré cp437, mais enregistré en UTF-8 :

ber '\xc3\xbcber'
ber u'\u251c\u255dber'

La chaîne d'octets a toujours les octets sur le disque (octets hexagonaux UTF-8). C3 BC ), mais les interprétait comme deux caractères cp437 au lieu d'un seul caractère encodé en UTF-8. Ces deux caractères ont été traduits en points de code Unicode, et tout s'imprime de manière incorrecte.

10voto

icktoofay Points 60218

Cela ne définit pas le format de la chaîne de caractères, mais le format du fichier. Même avec cet en-tête, "hello" est une chaîne d'octets, pas une chaîne Unicode. Pour la rendre Unicode, vous allez devoir utiliser u"hello" partout. L'en-tête n'est qu'une indication du format à utiliser lors de la lecture du document .py fichier.

0 votes

Je me suis trompé alors, je pensais que c'était la même chose. Donc l'utilisation des chaînes unicode est pour l'internationalisation ?

0 votes

@Oscar : Oui, pour la plupart. Si vous créez un site web avec Django ou autre et qu'il doit gérer des personnes avec des caractères non ASCII, alors c'est une autre utilisation possible.

7voto

ebt Points 1205

La définition de l'en-tête sert à définir l'encodage du code lui-même, et non les chaînes de caractères qui en résultent au moment de l'exécution.

mettre un caractère non-ascii comme dans le python script sans la définition de l'en-tête utf-8 lancera un avertissement

error

-1voto

tecnobillo Points 131

J'ai fait le module suivant appelé unicoder pour pouvoir faire la transformation sur les variables :

import sys
import os

def ustr(string):

    string = 'u"%s"'%string

    with open('_unicoder.py', 'w') as script:

        script.write('# -*- coding: utf-8 -*-\n')
        script.write('_ustr = %s'%string)

    import _unicoder
    value = _unicoder._ustr

    del _unicoder
    del sys.modules['_unicoder']

    os.system('del _unicoder.py')
    os.system('del _unicoder.pyc')

    return value

Ensuite, dans votre programme, vous pourriez faire ce qui suit :

# -*- coding: utf-8 -*-

from unicoder import ustr

txt = 'Hello, Unicode World'
txt = ustr(txt)

print type(txt) # <type 'unicode'>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X