web-dev-qa-db-fra.com

Données SQLite, python, unicode et non utf

J'ai commencé par essayer de stocker des chaînes dans sqlite en utilisant python, et j'ai reçu le message:

sqlite3.ProgrammingError: Vous ne devez pas utiliser de bytestrings 8 bits sauf si vous utilisez une text_factory qui peut interpréter des bytestrings 8 bits (comme text_factory = str). Il est fortement recommandé de basculer simplement votre application vers des chaînes Unicode.

Ok, je suis passé aux chaînes Unicode. Puis j'ai commencé à recevoir le message:

sqlite3.OperationalError: impossible de décoder vers la colonne UTF-8 'tag_artist' avec le texte 'Sigur Rós'

lorsque vous essayez de récupérer des données de la base de données. Plus de recherches et j'ai commencé à l'encoder dans utf8, mais ensuite 'Sigur Rós' commence à ressembler à 'Sigur Rós'

note: Ma console a été configurée pour s'afficher en 'latin_1' comme l'a souligné @John Machin.

Ce qui donne? Après avoir lu this , décrivant exactement la même situation dans laquelle je me trouve, il semble que le conseil est d'ignorer les autres conseils et d'utiliser des bytestrings 8 bits après tout.

Je ne savais pas grand-chose sur l'unicode et l'utf avant de commencer ce processus. J'ai beaucoup appris au cours des dernières heures, mais je ne sais toujours pas s'il existe un moyen de convertir correctement "ó" du latin-1 en utf-8 et de ne pas le modifier. Si ce n'est pas le cas, pourquoi sqlite "recommande-t-il fortement" de basculer mon application vers des chaînes unicode?


Je vais mettre à jour cette question avec un résumé et un exemple de code de tout ce que j'ai appris au cours des dernières 24 heures afin que quelqu'un à ma place puisse avoir un guide plus facile. Si les informations que je poste sont fausses ou trompeuses de quelque manière que ce soit, dites-le-moi et je mettrai à jour, ou l'un de vous les gars seniors peut mettre à jour.


Résumé des réponses

Permettez-moi d'abord d'énoncer l'objectif tel que je le comprends. Le but du traitement de divers encodages, si vous essayez de convertir entre eux, est de comprendre quel est votre encodage source, puis de le convertir en unicode en utilisant cet encodage source, puis de le convertir en l'encodage souhaité. Unicode est une base et les encodages sont des mappages de sous-ensembles de cette base. utf_8 a de la place pour chaque caractère en unicode, mais parce qu'ils ne sont pas au même endroit que, par exemple, latin_1, une chaîne encodée en utf_8 et envoyée à une console latin_1 ne ressemblera pas à ce que vous attendez. Dans python le processus d'accès à l'unicode et à un autre encodage ressemble à:

str.decode('source_encoding').encode('desired_encoding')

ou si la chaîne est déjà en unicode

str.encode('desired_encoding')

Pour sqlite, je ne voulais pas vraiment l'encoder à nouveau, je voulais le décoder et le laisser au format unicode. Voici quatre choses dont vous devrez peut-être être conscient lorsque vous essayez de travailler avec unicode et les encodages en python.

  1. L'encodage de la chaîne avec laquelle vous souhaitez travailler et l'encodage que vous souhaitez obtenir.
  2. L'encodage du système.
  3. L'encodage de la console.
  4. L'encodage du fichier source

Élaboration:

(1) Lorsque vous lisez une chaîne à partir d'une source, elle doit avoir un certain encodage, comme latin_1 ou utf_8. Dans mon cas, je reçois des chaînes de noms de fichiers, donc malheureusement, je pourrais obtenir n'importe quel type d'encodage. Windows XP utilise UCS-2 (un système Unicode) comme type de chaîne natif, ce qui me semble tricher. Heureusement pour moi, les caractères de la plupart des noms de fichiers ne seront pas composés de plus d'un type de codage source, et je pense que tous les miens étaient soit complètement latin_1, soit complètement utf_8, soit tout simplement ascii (qui est un sous-ensemble des deux). Je les ai donc lus et décodés comme s'ils étaient encore dans latin_1 ou utf_8. Il est possible, cependant, que vous puissiez avoir latin_1 et utf_8 et tous les autres caractères mélangés ensemble dans un nom de fichier sous Windows. Parfois, ces caractères peuvent apparaître sous forme de cases, d'autres fois ils semblent simplement mutilés et d'autres fois ils semblent corrects (caractères accentués et ainsi de suite).

(2) Python a un encodage système par défaut qui est défini lorsque python démarre et ne peut pas être modifié pendant l'exécution. Voir ici = pour plus de détails. Sale résumé ... et bien voici le fichier que j'ai ajouté:

\# sitecustomize.py  
\# this file can be anywhere in your Python path,  
\# but it usually goes in ${pythondir}/lib/site-packages/  
import sys  
sys.setdefaultencoding('utf_8')  

Ce codage système est celui qui est utilisé lorsque vous utilisez la fonction unicode ("str") sans aucun autre paramètre de codage. Pour dire cela d'une autre manière, python essaie de décoder "str" ​​en unicode sur la base du codage système par défaut.

(3) Si vous utilisez IDLE ou le python en ligne de commande, je pense que votre console s'affichera selon l'encodage système par défaut. J'utilise pydev avec Eclipse pour une raison quelconque, j'ai donc dû entrer dans les paramètres de mon projet, modifier les propriétés de configuration de lancement de mon script de test, aller dans l'onglet Commun et changer la console de latin-1 à utf-8 pour que Je pouvais confirmer visuellement ce que je faisais.

(4) Si vous souhaitez avoir des chaînes de test, par exemple

test_str = "ó"

dans votre code source, alors vous devrez dire python quel type d'encodage vous utilisez dans ce fichier. (Pour info: quand j'ai mal tapé un encodage, j'ai dû ctrl-Z parce que mon fichier est devenu illisible.) Ceci est facilement accompli en mettant une ligne comme ça en haut de votre fichier de code source:

# -*- coding: utf_8 -*-

Si vous ne disposez pas de ces informations, python essaie d'analyser votre code en ascii par défaut, et ainsi:

SyntaxError: Non-ASCII character '\xf3' in file _redacted_ on line 81, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

Une fois que votre programme fonctionne correctement, ou, si vous n'utilisez pas la console de python ou toute autre console pour regarder la sortie, vous ne vous soucierez probablement que du numéro 1 de la liste. La valeur par défaut du système et le codage de la console ne sont pas si importants, sauf si vous devez regarder la sortie et/ou si vous utilisez la fonction unicode () intégrée (sans aucun paramètre de codage) au lieu de la fonction string.decode (). J'ai écrit une fonction de démonstration que je vais coller au bas de ce gigantesque désordre qui, je l'espère, illustre correctement les éléments de ma liste. Voici une partie de la sortie lorsque j'exécute le caractère "ó" via la fonction de démonstration, montrant comment différentes méthodes réagissent au personnage en entrée. L'encodage de mon système et la sortie de la console sont tous deux définis sur utf_8 pour cette exécution:

'�' = original char <type 'str'> repr(char)='\xf3'
'?' = unicode(char) ERROR: 'utf8' codec can't decode byte 0xf3 in position 0: unexpected end of data
'ó' = char.decode('latin_1') <type 'unicode'> repr(char.decode('latin_1'))=u'\xf3'
'?' = char.decode('utf_8')  ERROR: 'utf8' codec can't decode byte 0xf3 in position 0: unexpected end of data

Maintenant, je vais changer l'encodage du système et de la console en latin_1, et j'obtiens cette sortie pour la même entrée:

'ó' = original char <type 'str'> repr(char)='\xf3'
'ó' = unicode(char) <type 'unicode'> repr(unicode(char))=u'\xf3'
'ó' = char.decode('latin_1') <type 'unicode'> repr(char.decode('latin_1'))=u'\xf3'
'?' = char.decode('utf_8')  ERROR: 'utf8' codec can't decode byte 0xf3 in position 0: unexpected end of data

Notez que le caractère "original" s'affiche correctement et que la fonction intégrée unicode () fonctionne maintenant.

Maintenant, je remets la sortie de ma console sur utf_8.

'�' = original char <type 'str'> repr(char)='\xf3'
'�' = unicode(char) <type 'unicode'> repr(unicode(char))=u'\xf3'
'�' = char.decode('latin_1') <type 'unicode'> repr(char.decode('latin_1'))=u'\xf3'
'?' = char.decode('utf_8')  ERROR: 'utf8' codec can't decode byte 0xf3 in position 0: unexpected end of data

Ici, tout fonctionne toujours comme la dernière fois, mais la console ne peut pas afficher correctement la sortie. Etc. La fonction ci-dessous affiche également plus d'informations que cela et, espérons-le, aiderait quelqu'un à comprendre où est l'écart dans leur compréhension. Je sais que toutes ces informations sont ailleurs et traitées de manière plus approfondie, mais j'espère que ce serait un bon point de départ pour quelqu'un qui essaie d'obtenir le codage avec python et/ou sqlite. Idées sont excellents, mais parfois le code source peut vous faire économiser un jour ou deux pour essayer de comprendre quelles fonctions font quoi.

Avertissements: Je ne suis pas un expert en encodage, j'ai mis cela ensemble pour aider ma propre compréhension. J'ai continué à construire dessus quand j'aurais probablement dû commencer à passer des fonctions comme arguments pour éviter autant de code redondant, donc si je peux, je le rendrai plus concis. De plus, utf_8 et latin_1 ne sont en aucun cas les seuls schémas d'encodage, ce ne sont que les deux avec lesquels je jouais parce que je pense qu'ils gèrent tout ce dont j'ai besoin. Ajoutez vos propres schémas d'encodage à la fonction de démonstration et testez votre propre entrée.

Encore une chose: il y a développeurs d'applications apparemment fous rendant la vie difficile sous Windows.

#!/usr/bin/env python
# -*- coding: utf_8 -*-

import os
import sys

def encodingDemo(str):
    validStrings = ()
    try:        
        print "str =",str,"{0} repr(str) = {1}".format(type(str), repr(str))
        validStrings += ((str,""),)
    except UnicodeEncodeError as ude:
        print "Couldn't print the str itself because the console is set to an encoding that doesn't understand some character in the string.  See error:\n\t",
        print ude
    try:
        x = unicode(str)
        print "unicode(str) = ",x
        validStrings+= ((x, " decoded into unicode by the default system encoding"),)
    except UnicodeDecodeError as ude:
        print "ERROR.  unicode(str) couldn't decode the string because the system encoding is set to an encoding that doesn't understand some character in the string."
        print "\tThe system encoding is set to {0}.  See error:\n\t".format(sys.getdefaultencoding()),  
        print ude
    except UnicodeEncodeError as uee:
        print "ERROR.  Couldn't print the unicode(str) because the console is set to an encoding that doesn't understand some character in the string.  See error:\n\t",
        print uee
    try:
        x = str.decode('latin_1')
        print "str.decode('latin_1') =",x
        validStrings+= ((x, " decoded with latin_1 into unicode"),)
        try:        
            print "str.decode('latin_1').encode('utf_8') =",str.decode('latin_1').encode('utf_8')
            validStrings+= ((x, " decoded with latin_1 into unicode and encoded into utf_8"),)
        except UnicodeDecodeError as ude:
            print "The string was decoded into unicode using the latin_1 encoding, but couldn't be encoded into utf_8.  See error:\n\t",
            print ude
    except UnicodeDecodeError as ude:
        print "Something didn't work, probably because the string wasn't latin_1 encoded.  See error:\n\t",
        print ude
    except UnicodeEncodeError as uee:
        print "ERROR.  Couldn't print the str.decode('latin_1') because the console is set to an encoding that doesn't understand some character in the string.  See error:\n\t",
        print uee
    try:
        x = str.decode('utf_8')
        print "str.decode('utf_8') =",x
        validStrings+= ((x, " decoded with utf_8 into unicode"),)
        try:        
            print "str.decode('utf_8').encode('latin_1') =",str.decode('utf_8').encode('latin_1')
        except UnicodeDecodeError as ude:
            print "str.decode('utf_8').encode('latin_1') didn't work.  The string was decoded into unicode using the utf_8 encoding, but couldn't be encoded into latin_1.  See error:\n\t",
            validStrings+= ((x, " decoded with utf_8 into unicode and encoded into latin_1"),)
            print ude
    except UnicodeDecodeError as ude:
        print "str.decode('utf_8') didn't work, probably because the string wasn't utf_8 encoded.  See error:\n\t",
        print ude
    except UnicodeEncodeError as uee:
        print "ERROR.  Couldn't print the str.decode('utf_8') because the console is set to an encoding that doesn't understand some character in the string.  See error:\n\t",uee

    print
    print "Printing information about each character in the original string."
    for char in str:
        try:
            print "\t'" + char + "' = original char {0} repr(char)={1}".format(type(char), repr(char))
        except UnicodeDecodeError as ude:
            print "\t'?' = original char  {0} repr(char)={1} ERROR PRINTING: {2}".format(type(char), repr(char), ude)
        except UnicodeEncodeError as uee:
            print "\t'?' = original char  {0} repr(char)={1} ERROR PRINTING: {2}".format(type(char), repr(char), uee)
            print uee    

        try:
            x = unicode(char)        
            print "\t'" + x + "' = unicode(char) {1} repr(unicode(char))={2}".format(x, type(x), repr(x))
        except UnicodeDecodeError as ude:
            print "\t'?' = unicode(char) ERROR: {0}".format(ude)
        except UnicodeEncodeError as uee:
            print "\t'?' = unicode(char)  {0} repr(char)={1} ERROR PRINTING: {2}".format(type(x), repr(x), uee)

        try:
            x = char.decode('latin_1')
            print "\t'" + x + "' = char.decode('latin_1') {1} repr(char.decode('latin_1'))={2}".format(x, type(x), repr(x))
        except UnicodeDecodeError as ude:
            print "\t'?' = char.decode('latin_1')  ERROR: {0}".format(ude)
        except UnicodeEncodeError as uee:
            print "\t'?' = char.decode('latin_1')  {0} repr(char)={1} ERROR PRINTING: {2}".format(type(x), repr(x), uee)

        try:
            x = char.decode('utf_8')
            print "\t'" + x + "' = char.decode('utf_8') {1} repr(char.decode('utf_8'))={2}".format(x, type(x), repr(x))
        except UnicodeDecodeError as ude:
            print "\t'?' = char.decode('utf_8')  ERROR: {0}".format(ude)
        except UnicodeEncodeError as uee:
            print "\t'?' = char.decode('utf_8')  {0} repr(char)={1} ERROR PRINTING: {2}".format(type(x), repr(x), uee)

        print

x = 'ó'
encodingDemo(x)

Merci beaucoup pour les réponses ci-dessous et surtout à @John Machin pour avoir répondu si minutieusement.

65
Nathan Spears

Je ne sais toujours pas s'il existe un moyen de convertir correctement 'ó' du latin-1 en utf-8 et de ne pas le modifier

repr () et unicodedata.name () sont vos amis quand il s'agit de déboguer de tels problèmes:

>>> oacute_latin1 = "\xF3"
>>> oacute_unicode = oacute_latin1.decode('latin1')
>>> oacute_utf8 = oacute_unicode.encode('utf8')
>>> print repr(oacute_latin1)
'\xf3'
>>> print repr(oacute_unicode)
u'\xf3'
>>> import unicodedata
>>> unicodedata.name(oacute_unicode)
'LATIN SMALL LETTER O WITH ACUTE'
>>> print repr(oacute_utf8)
'\xc3\xb3'
>>>

Si vous envoyez oacute_utf8 à un terminal configuré pour latin1, vous obtiendrez A-tilde suivi de exposant-3.

Je suis passé aux chaînes Unicode.

Comment appelez-vous les chaînes Unicode? UTF-16?

Ce qui donne? Après avoir lu ceci, décrit exactement la même situation dans laquelle je me trouve, il semble que le conseil est d'ignorer les autres conseils et d'utiliser des octets de 8 bits après tout.

Je ne peux pas imaginer comment cela vous semble. L'histoire véhiculée était que les objets Unicode dans Python et UTF-8 dans la base de données étaient la voie à suivre. Cependant, Martin a répondu à la question d'origine, en donnant une méthode ("fabrique de texte" ) pour que l'OP puisse utiliser latin1 - cela ne constituait PAS une recommandation!

Mise à jour en réponse à ces autres questions soulevées dans un commentaire:

Je n'ai pas compris que les caractères unicode contenaient toujours un encodage implicite. Suis-je en train de dire ça?

Non. Un codage est un mappage entre Unicode et autre chose, et vice versa. Un caractère Unicode n'a pas d'encodage, implicite ou autre.

Il me semble que l'unicode ("\ xF3") et "\ xF3" .decode ('latin1') sont les mêmes lorsqu'ils sont évalués avec repr ().

Tu peux répéter s'il te plait? Ça ne me ressemble pas:

>>> unicode("\xF3")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xf3 in position 0: ordinal
not in range(128)
>>> "\xF3".decode('latin1')
u'\xf3'
>>>

Peut-être que vous vouliez dire: u'\xf3' == '\xF3'.decode('latin1') ... c'est certainement vrai.

Il est également vrai que unicode(str_object, encoding) fait la même chose que str_object.decode(encoding) ... y compris le fait de sauter quand un encodage inapproprié est fourni.

Est-ce une heureuse circonstance

Que les 256 premiers caractères en Unicode soient les mêmes, code pour code, car les 256 caractères en latin1 sont une bonne idée. Étant donné que les 256 caractères latin1 possibles sont mappés sur Unicode, cela signifie que N'IMPORTE QUEL octet de 8 bits, TOUT Python str peut être décodé en unicode sans qu'une exception ne soit levée. C'est comme cela devrait être .

Cependant, il existe certaines personnes qui confondent deux concepts bien distincts: "mon script s'exécute complètement sans qu'aucune exception ne soit déclenchée" et "mon script est sans erreur". Pour eux, latin1 est "un piège et une illusion".

En d'autres termes, si vous avez un fichier qui est réellement encodé en cp1252 ou gbk ou koi8-u ou quoi que ce soit et que vous le décodez en utilisant latin1, l'Unicode résultant sera des ordures et Python (ou tout autre autre langue) ne signalera pas d'erreur - il n'a aucun moyen de savoir que vous avez commis une bêtise.

ou est-ce que l'unicode ("str") va toujours retourner le décodage correct?

Tout comme cela, avec l'encodage par défaut étant ascii, il retournera le bon code si le fichier est réellement encodé en ASCII. Sinon, ça va exploser.

De même, si vous spécifiez le codage correct, ou un sur-ensemble du codage correct, vous obtiendrez le résultat correct. Sinon, vous obtiendrez du charabia ou une exception.

Bref, la réponse est non.

Sinon, quand je reçois une chaîne python contenant un jeu de caractères possible, comment savoir comment la décoder?

Si l'objet str est un document XML valide, il sera spécifié à l'avance. La valeur par défaut est UTF-8. S'il s'agit d'une page Web correctement construite, elle doit être spécifiée à l'avance (recherchez "charset"). Malheureusement, de nombreux rédacteurs de pages Web passent entre leurs dents (ISO-8859-1 aka latin1, devrait être Windows-1252 aka cp1252; ne gaspillez pas les ressources en essayant de décoder gb2312, utilisez plutôt gbk). Vous pouvez obtenir des indices de la nationalité/langue du site Web.

UTF-8 vaut toujours la peine d'être essayé. Si les données sont ascii, cela fonctionnera bien, car ascii est un sous-ensemble de utf8. Une chaîne de texte qui a été écrite en utilisant des caractères non-ascii et qui a été encodée dans un encodage autre que utf8 échouera certainement avec une exception si vous essayez de la décoder en utf8.

Toutes les heuristiques ci-dessus et plus et beaucoup de statistiques sont encapsulées dans chardet , un module pour deviner l'encodage de fichiers arbitraires. Cela fonctionne généralement bien. Cependant, vous ne pouvez pas rendre les logiciels à l'épreuve des idiots. Par exemple, si vous concaténez des fichiers de données écrits certains avec le codage A et certains avec le codage B, et que vous alimentez le résultat en chardet, la réponse est susceptible de coder C avec un niveau de confiance réduit, par ex. 0,8. Vérifiez toujours la partie confiance de la réponse.

Si tout le reste échoue:

(1) Essayez de demander ici, avec un petit échantillon à l'avant de vos données ... print repr(your_data[:400]) ... et toutes les informations collatérales sur sa provenance que vous avez.

(2) Des recherches russes récentes sur techniques de récupération de mots de passe oubliés semblent tout à fait applicables à la déduction de codages inconnus.

Mise à jour 2 BTW, n'est-il pas temps que vous ouvriez une autre question? -)

Une dernière chose: il y a apparemment des caractères que Windows utilise comme Unicode pour certains caractères qui ne sont pas le bon Unicode pour ce caractère, donc vous devrez peut-être mapper ces caractères aux bons si vous voulez les utiliser dans d'autres programmes qui sont attendant ces personnages au bon endroit.

Ce n'est pas Windows qui le fait; c'est un tas de développeurs d'applications fous. Il est plus compréhensible que vous n'ayez pas paraphrasé, mais cité le premier paragraphe de l'article d'effbot auquel vous avez fait référence:

Certaines applications ajoutent des caractères CP1252 (Windows, Europe occidentale) aux documents marqués ISO 8859-1 (Latin 1) ou à d'autres codages. Ces caractères ne sont pas des caractères ISO-8859-1 valides et peuvent provoquer toutes sortes de problèmes dans les applications de traitement et d'affichage.

Contexte:

La plage U + 0000 à U + 001F inclus est désignée dans Unicode comme "C0 Control Characters". Ceux-ci existent également en ASCII et latin1, avec les mêmes significations. Ils incluent des choses familières telles que le retour chariot, le saut de ligne, la cloche, le retour arrière, la tabulation et d'autres qui sont rarement utilisés.

La plage U + 0080 à U + 009F inclus est désignée dans Unicode comme "Caractères de contrôle C1". Ceux-ci existent également en latin1, et comprennent 32 caractères pour lesquels personne en dehors d'unicode.org ne peut imaginer une utilisation possible.

Par conséquent, si vous exécutez un décompte de fréquence de caractères sur vos données unicode ou latin1 et que vous trouvez des caractères dans cette plage, vos données sont corrompues. Il n'y a pas de solution universelle; cela dépend de la façon dont il a été corrompu. Les caractères mai ont la même signification que les caractères cp1252 aux mêmes positions, et donc la solution de l'effbot fonctionnera. Dans un autre cas que j'ai examiné récemment, les caractères douteux semblent avoir été causés par la concaténation de fichiers texte encodés en UTF-8 et un autre encodage qui devait être déduit en fonction des fréquences des lettres dans la langue (humaine) dans laquelle les fichiers étaient écrit en.

34
John Machin

UTF-8 est le codage par défaut des bases de données SQLite. Cela apparaît dans des situations comme "SELECT CAST (x'52C3B373 'AS TEXT);". Cependant, la bibliothèque SQLite C ne vérifie pas réellement si une chaîne insérée dans une base de données est UTF-8 valide.

Si vous insérez un objet Python unicode (ou objet str dans 3.x), la bibliothèque Python sqlite3 le convertira automatiquement en UTF-8. Mais si vous insérez un objet str, il sera juste supposez la chaîne est UTF-8, car Python 2.x "str" ​​ne connaît pas son encodage. C'est une raison de préférer les chaînes Unicode.

Cependant, cela ne vous aide pas si vos données sont cassées pour commencer.

Pour corriger vos données, faites

db.create_function('FIXENCODING', 1, lambda s: str(s).decode('latin-1'))
db.execute("UPDATE TheTable SET TextColumn=FIXENCODING(CAST(TextColumn AS BLOB))")

pour chaque colonne de texte de votre base de données.

21
dan04

J'ai résolu ce problème pysqlite en définissant:

conn.text_factory = lambda x: unicode(x, 'utf-8', 'ignore')

Par défaut, text_factory est défini sur unicode (), qui utilisera l'encodage par défaut actuel (ascii sur ma machine)

19
hoju

Bien sûr que oui. Mais vos données sont déjà cassées dans la base de données, vous devrez donc les corriger:

>>> print u'Sigur Rós'.encode('latin-1').decode('utf-8')
Sigur Rós

Mes problèmes Unicode avec Python 2.x (Python 2.7.6 pour être spécifique) ont résolu ce problème:

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

from __future__ import unicode_literals
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

Cela a également résolu l'erreur que vous mentionnez au début du message:

sqlite3.ProgrammingError: Vous ne devez pas utiliser de bytestrings 8 bits à moins que ...

[~ # ~] modifier [~ # ~]

sys.setdefaultencoding est un hack sale . Oui, cela peut résoudre les problèmes UTF-8, mais tout a un prix. Pour plus de détails, reportez-vous aux liens suivants:

3
Dušan Maďar