UnicodeDecodeError: 'ascii' codec ne peut pas décoder les octets 0x92 en position 47: ordinal pas in range(128)
Je suis en train d'écrire des données dans un StringIO objet à l'aide de Python et puis, finalement, charger ces données dans une base de données postgres à l'aide de psycopg2 de copy_from() fonction.
D'abord quand j'ai fait cela, la copy_from() a été de lancer une erreur: ERREUR: invalid séquence d'octets pour l'encodage "UTF-8": 0xc92 j'ai Donc suivi cette question.
J'ai compris que ma base de données Postgres a l'encodage UTF8.
Le fichier/StringIO objet que je suis en train d'écrire mes données montre son encodage comme suit:
setgid Non-ISO ASCII étendu texte en anglais, avec des lignes très longues, avec CRLF ligne terminateurs
J'ai essayé d'encoder toutes les chaînes que je suis en train d'écrire le fichier intermédiaire/StringIO objet en format UTF8. Pour ce faire utilisé .coder(encoding='UTF-8',erreurs= "stricte")) pour chaque chaîne.
C'est l'erreur que j'ai maintenant:
UnicodeDecodeError: 'ascii' codec ne peut pas décoder les octets 0x92 en position 47: ordinal pas in range(128)
Ça veut dire quoi? Comment puis-je résoudre ce problème?
EDIT:
J'utilise Python 2.7
Certaines pièces de mon code:
J'ai lu à partir d'une base de données MySQL qui contient des données codées en UTF-8 par MySQL Workbench.
C'est à quelques lignes de code pour l'écriture de mes données (obtenue à partir de bases de données MySQL) pour StringIO objet:
# Populate the table_data variable with rows delimited by \n and columns delimited by \t
row_num=0
for row in cursor.fetchall() :
# Separate rows in a table by new line delimiter
if(row_num!=0):
table_data.write("\n")
col_num=0
for cell in row:
# Separate cells in a row by tab delimiter
if(col_num!=0):
table_data.write("\t")
table_data.write(cell.encode(encoding='UTF-8',errors='strict'))
col_num = col_num+1
row_num = row_num+1
C'est le code qui écrit à la base de données Postgres de mon StringIO objet table_data:
cursor = db_connection.cursor()
cursor.copy_from(table_data, <postgres_table_name>)
- Afficher votre code svp
- Qui MySQL wrapper utilisez-vous?
- Aussi, au lieu de montrer "certaines pièces de mon code", créer un un minimum, de manière complète, vérifiable exemple et de la poster ici.
- Je suis à l'aide de MySQLdb que le paquet python pour récupérer les données de MySQL
- Pendant ce temps, après vos mises à jour et les réponses, il n'y a pas encore de MCVE, et d'autres informations critiques n'est visible que dans les commentaires, ce qui signifie que toute personne à la recherche parce qu'ils veulent aider les gens comme vous ou parce qu'ils ont un problème similaire de ne pas le voir.
- Je vais essayer d'ajouter un peu plus de code. Je ne peux pas donner beaucoup plus de code car pour des raisons de sécurité.
- Lire le lié de l'aide. Personne ne veut de votre code réel, ils veulent un minimum, de manière complète, vérifiable exemple qui illustre le problème.
Vous devez vous connecter pour publier un commentaire.
Le problème, c'est que vous êtes d'appel
encode
sur unstr
objet.Un
str
est une chaîne d'octets, qui représentent habituellement de texte codé en quelque sorte, comme UTF-8. Lorsque vous appelezencode
sur ce, il doit être décodé retour au texte, le texte peut être ré-encodé. Par défaut, Python n'est qu'en appelants.decode(sys.getgetdefaultencoding())
, etgetdefaultencoding()
renvoie généralement'ascii'
.Donc, vous parlez de texte UTF-8, le décodage comme si c'était ASCII, puis de le ré-encoder en UTF-8.
La solution générale est d'appeler explicitement
decode
avec le bon encodage, au lieu de laisser Python utiliser la valeur par défaut, puisencode
le résultat.Mais quand le bon encodage est déjà celui que vous voulez, la solution plus simple: il suffit de sauter la
.decode('utf-8').encode('utf-8')
et il suffit d'utiliser l'UTF-8str
comme l'UTF-8str
qu'il ne l'est déjà.Ou, à défaut, si votre MySQL wrapper a une fonctionnalité pour vous permettre de spécifier un encodage et de revenir
unicode
valeurs pourCHAR
/VARCHAR
/TEXT
colonnes au lieu destr
valeurs (par exemple, dans MySQLdb, vous passezuse_unicode=True
à laconnect
appel, oucharset='UTF-8'
si votre base de données est trop vieux pour l'auto-détection), il suffit de faire cela. Ensuite, vous aurezunicode
objets, et vous pouvez les appeler.encode('utf-8')
sur eux.En général, la meilleure façon de traiter avec Unicode problèmes est le dernier—décoder tout aussi tôt que possible, faire tout le traitement en Unicode, et puis l'encoder le plus tard possible. Mais de toute façon, vous devez être cohérent. Ne l'appelez pas
str
sur quelque chose qui pourrait être ununicode
; ne pas concaténer unestr
littérale à uneunicode
ou passer de l'un à sesreplace
méthode; etc. Toutes les fois que vous mélanger et assortir, Python va convertir implicitement pour vous, à l'aide de votre encodage par défaut, qui n'est presque jamais ce que vous voulez.Comme une note de côté, c'est l'une des nombreuses choses que Python 3.x Unicode de changements de l'aide. Tout d'abord,
str
est maintenant de texte Unicode, pas codé octets. Plus important encore, si vous ont codé en octets, par exemple, dans unbytes
objet, l'appel deencode
vous donnera uneAttributeError
au lieu d'essayer d'en silence décoder de sorte qu'il peut ré-encoder. Et, de même, essayer de mélanger et assortir Unicode et d'octets de vous donner un évidentTypeError
, au lieu d'une conversion implicite qui réussit, dans certains cas, et donne un message énigmatique sur un encoder ou de décoder vous ne le demandez pas dans d'autres.unicode
objets au lieu destr
—ce qui est une bonne idée, vous ne pouvez pas vous appelerstr
sur eux, parce que cela va immédiatement essayer de coder votre jeu de caractères par défaut. Et vous ne devriez pas mélanger et assortirunicode
etstr
objets comme vous le faites, parce que, aussi, implicitement, encoder ou de décoder un ou l'autre; l'utilisationreplace(u"\r", u" ")
et la comme. (En fait,"\r"
est mauvais d'une autre façon: si vous avez des barres obliques inverses, soit leur échapper, ou de l'utilisation d'un raw un littéral de chaîne.)latin1_swedish_ci
tables (avec des versions plus récentes, les problèmes peuvent aller loin si vous le laissez au large de lacharset=
et le laisser détecter automatiquement, mais ils ne peuvent pas). Mais ne vous inquiétez pas, sauf si/jusqu'à ce que vous y arrivez; de la première à obtenir votre code de travail avec l'UTF-8 tables, puis test sur le suédois ceux.unicode
package importé, mais vous ne devriez pas besoin d'une telle chose. Aussi, je ne sais pas pourquoi vous essayez d'appelerstr
sur quoi que ce soit. Avant, vous aviez déjà unstr
, il était donc inutile. Maintenant, vous avez ununicode
, et de la façon d'encoder un de ceux àstr
est avec leencode
méthode. Et vous certainement ne pas avoir à jeter des accents et des guillemets et des emoji et ainsi de suite juste pour copier vos données à partir d'une base de données à l'autre. Encore une fois, veuillez lire le guide.copy_from
peut prendre les fichiers Unicode: "lecture de données à partir de fichiers de la mise en œuvre de l'oi.TextIOBase interface sont encodés dans la connexion de l'encodage lors de l'envoi à l'arrière-plan". Donc, si vous utilisez seulementio.StringIO
au lieu deStringIO.StringIO
, vous n'avez pas besoin de coder à tous. MySQLdb vous donne Unicode, vous devez traiter comme Unicode, vous la donnez à psycopg comme Unicode, tous vos programmes en aller.