J'ai un script Python 2.6 qui gronde sur des caractères spéciaux encodés en latin-1, que je récupère à partir d'une base de données SQL Server. J'aimerais imprimer ces personnages, mais je suis un peu limité car j'utilise une bibliothèque qui appelle l'usine code> unicode code>, et je ne sais pas comment faire python utiliser un codec autre que Le script est un outil simple pour renvoyer des données de recherche à partir d'une base de données sans avoir à exécuter le SQL directement dans un éditeur SQL. J'utilise le Prettytable 0.5 Bibliothèque pour afficher les résultats. P> Le noyau du script est ce bit de code. Les tuples que je reçois du curseur contiennent des données entier et de chaîne, et aucune donnée Unicode. (J'utiliserais mais la colonne ASCII code>. adodbapi code> au lieu de pyodbc code>, qui me ferait unicode, mais adodbapi code> me donne d'autres problèmes.) P> xxx pré> nom code> peut contenir des caractères qui tombent en dehors de la gamme ASCII. Je vais parfois obtenir un message d'erreur comme celui-ci, dans la ligne 222 de pretthable.pyc code>, quand il passe au t.add_row code> appel: p> x = pyodbc.connect(cxnstring)
r = x.cursor()
r.execute(sql)
t = PrettyTable(columns)
for rec in r:
urec = [s.decode('latin-1') if isinstance(s, str) else s for s in rec]
t.add_row(urec)
r.close()
x.close()
t.set_field_align("ID", 'r')
t.set_field_align("Name", 'l')
print t.get_string().encode('latin-1')
3 Réponses :
Ajoutez ceci au début du module: ou décode la chaîne à vous-même. p> [modifier] p> Ça a été Un certain temps depuis que j'ai joué avec unicode, mais j'espère que cet exemple montrera comment convertir de latin1 en Unicode: p> [modifier] p> Documentation: < BR>
http://docs.python.org/howto/unicode.html
http://docs.python.org/library/codecs.html p> p>
J'ai essayé de mettre le codage au sommet de mes scripts, mais cela ne fonctionne toujours pas. Je vais essayer le décodage explicite, mais j'espère qu'il y a une solution plus générale.
Vous ne voulez probablement pas définir la codage: latin1. Cela modifie l'encodage de la source du script, pas ses données.
@Glenn: J'ai suggéré que parce que je pensais que imprimer t code> peut imprimer des chaînes brutes latin1.
Mon script n'a pas de littéraux de chaîne avec des caractères non ASCII. Donc, cela ne devrait pas être un facteur.
@Bastien Léonard: Les données que je reçoivent de la base de données ne sont pas unicode. Le caractère en question est 0xed. Je ne peux pas décoder 0xed avec le codec ASCII. Existe-t-il un moyen de modifier le codage par défaut uniquement pour cette fonction unique, de sorte que Unicode code> fonctionnerait?
@Bastien Léonard: J'ai une combinaison qui a finalement travaillé. Je vais le classer jusqu'à la fin de ma question. Merci pour l'aide.
Peut-être essayez peut-être de décoder les chaînes codées latin1 à UNICODE?
t.add_row((value.decode('latin1') for value in rec))
t.add_row ([S.Decode ("Latin-1 ') Si IsInstance (S, STR) ailleurs S pour S en Rec]) # Je pense que vous vouliez dire ceci (ou quelque chose comme ça).
Probablement, en fonction de la nécessité de ce que cette pretthable est nécessaire.
Après un coup d'œil rapide à la source pour PrettyTable, il semble que cela fonctionne sur des objets Unicode en interne (voir ASCII est un sous-ensemble em> de latin-1, ce qui signifie que si vous convertissez d'ASCII en latin-1, vous ne devriez pas avoir de problèmes. L'inverse cependant, n'est pas vrai; Toutes les caractères latin-1 ne sont pas toutes les caractères ASCII. Démontrer ceci: p> _stringify_row code>, add_row code> et add_column code> , par example). Comme il ne sait pas ce qui codant sur vos chaînes d'entrée utilisez, il utilise le codage par défaut, habituellement ASCII A>. >>> s = u'\xed\x31\x32\x33'
>>> print s
# FAILS: Python calls "s.decode('ascii')", but ascii codec can't decode '\xed'
>>> print s.decode('ascii')
# FAILS: Same as above
>>> print s.decode('latin-1')
Ã123
Si elle utilise des objets Unicode en interne, il devrait y avoir un moyen d'obtenir des objets Unicode et d'éviter de les convertir inutilement. Tant que vous utilisez toujours des objets Unicode, vous évitez la plupart de ce gâchis (c'est ainsi que Python 3 fonctionne toujours).
Je crois que ça fait: "get_string".
@ elo80ka, les données sont vraiment stockées comme latin-1. J'ai vérifié cela avant d'écrire le script. Aussi (en Python 2.6 au moins), INTS ne peut pas être contraint à l'aide de Unicode (int_value, 'latin-1') code>, même si Unicode (int_value) code> fonctionne. @Glenn Maynard, imprimer les résultats implique un décodage, défini ou non explicitement. J'ai dû utiliser t.get_string (). Encode ("Latin-1 ') Code> Ouais, j'attends avec impatience l'adoption généralisée de PY3K, de sorte que toutes les chaînes soient unicode. Cela économiserait beaucoup de tracas.
@Eksortso: Vous avez raison ... Les ensembles de caractères n'ont pas vraiment de sens pour les chiffres de toute façon.