Seite 1 von 1
[gelöst]Decoding Problem mit MySQLdb
Verfasst: Donnerstag 8. Februar 2007, 16:42
von ebel
Hallo Python-Forumianer,
Habe folgende Tabelle
CREATE TABLE `tablename` (
`name` varchar(3) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO `tablename` VALUES ('—');
Versuche nun folgendes
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: utf-8 -*-
import MySQLdb
c=MySQLdb.connect("localhost","user","passwort","databank").cursor()
c.execute("Select name from tablename")
name=c.fetchone()[0]
print type(name)
# ergibt: <type 'str'>
sql="Select '%s'" % (name)
print sql
# ergibt: Select '—'
# ACHTUNG: Dies ist ein langer Gedankenstrich
c.execute(sql)
Fehlerausgabe:
Traceback (most recent call last):
File "/home/ceb/temp/test.py", line 13, in <module>
c.execute(sql)
File "/usr/lib/python2.5/site-packages/MySQLdb/cursors.py", line 146, in execute
query = query.encode(charset)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 8: ordinal not in range(128)
Wie muss man decoden um das SQL statement ausführen zu können? Oder ist das ein ganz anderes Probelm was ich bisher übersehen habe?
Schon mal vielen Dank im voraus
Gruss
ebel
Verfasst: Donnerstag 8. Februar 2007, 18:13
von jens
Im connect solltest du am besten das kwarg charset nutzten und z.B. auf "utf8" stellen.
Dann fütterst du MySQL mit unicode Strings... Das sollte gehen...
Verfasst: Donnerstag 8. Februar 2007, 20:04
von Y0Gi
Welche Version von MySQLdb verwendest du? Vermutlich nicht die AFAIK aktuellste 1.2.2b1, denn da sollte das Problem behoben sein. Alternativ kannst du eine 1.2.1_p1 (vermutlich auch andere) mit dem
hier beschriebenen Patch anpassen.
Vielleicht reicht es aber auch schon, nicht printf-%-Formatierung zu benutzen, sondern die Variablen als Parameter an .execute() zu übergeben. Genau das hat Andy Dustman (der Entwickler) nämlich auch sehr oft bei solchen Problemen entgegnet.
Einfach lösung gefunden für MySQLdb 1.2.1_p2 bug
Verfasst: Freitag 9. Februar 2007, 12:01
von ebel
LieberY0Gi,
vielen, vielen Dank für den nützlichen Verweis auf
hier beschriebenen Patch. Ungaublich einfach die Lösung.
Also, kurz zusammen gefasst:
Das Problem betrifft anscheinend nur MySQLdb version 1.2.1_p2
Lösung:
in "/usr/lib/python2.5/site-packages/MySQLdb/cursors.py", line 146
austauschen gegen:
Code: Alles auswählen
if isinstance(query, unicode):
query = query.encode(charset)
Das wars.
Gruss
ebel
Verfasst: Freitag 9. Februar 2007, 12:04
von Y0Gi
Aber bitte. Hat mich selbst genug Nerven gekostet...
Mir ist ein Rätsel, warum 1.2.2 immer noch nicht stable geworden ist, 1.2.1_p1 ist praktisch IMHO unbrauchbar.
Re: Einfach lösung gefunden für MySQLdb 1.2.1_p2 bug
Verfasst: Freitag 9. Februar 2007, 12:57
von jens
ebel hat geschrieben:Also, kurz zusammen gefasst:
Das Problem betrifft anscheinend nur MySQLdb version 1.2.1_p2
Lösung:
in "/usr/lib/python2.5/site-packages/MySQLdb/cursors.py", line 146
austauschen gegen:
Code: Alles auswählen
if isinstance(query, unicode):
query = query.encode(charset)
Ich weiß nicht ob du damit glück haben wirst.
Ich mache es anders: Ich baue den connect mit "charset=utf8" oder "use_unicode=True" auf. Danach setzte ich den SQL-Befehl "SET NAMES 'utf8';" ab.
Das scheint gut zu funktionieren. Das ist im Prinzip auch das selbe wie der trac Patch:
http://trac.edgewall.org/attachment/tic ... ysql.patch
Siehe auch:
http://www.python-forum.de/post-52110.html#52110
Re: Einfach lösung gefunden für MySQLdb 1.2.1_p2 bug
Verfasst: Freitag 9. Februar 2007, 13:06
von ebel
Hallo Jens,
vielen Dank für Deinen zusätzlichen Hinweis. Mehrere Lösungen sind immer gut!!!
Also im Moment bin ich glücklich mit der Lösung, da ich meine Programme nicht ändern muss und alles wie bisher wunderbar funktioniert. Ist aber vielleicht keine saubere Lösung und zieht Folgefehler nach sich. Sieht Du da eine Gefahr?
Gruss
ebel
Edit (jens): FULL QUOTES bitte unterlassen, siehe:
http://www.python-forum.de/topic-9352.html
Verfasst: Freitag 9. Februar 2007, 13:11
von jens
Naja, ich würde es ehr vermeiden in den Quellentexten von MySQLdb rum zu patchen. Wenn du das kannst, solltest du auch einfach eine neue Version installieren können, oder nicht?
Neues MySQLdb 1.2.2 Modul installaieren
Verfasst: Freitag 9. Februar 2007, 13:38
von ebel
Hallo Jens,
Du hast sicherlich recht: Im Quelltext rumfummeln ist immer ein bisschen gefährlich. Wenn man aber den Quelltext genauer anschaut so sieht es als ob der Entwickler Andy Dustman an allen anderen Stellen in cursors.py eben genau das macht.
Ok, nicht genau das selbe, denn er macht folgendes:
Code: Alles auswählen
from types import UnicodeType
if type(q) is UnicodeType:
q = q.encode(charset)
Wobei das aber das selbe bedeutet.
Ich werde aber 1.2.2 sofort installieren sobald es stable ist.
Gruß und nochmals vielen Dank für Deinen Hinweis
ebel
Verfasst: Freitag 9. Februar 2007, 13:40
von jens
Aha! Ich frage mich warum er nicht if isinstance(q, unicode) macht...
Verfasst: Freitag 9. Februar 2007, 13:47
von Y0Gi
jens hat geschrieben:Naja, ich würde es ehr vermeiden in den Quellentexten von MySQLdb rum zu patchen. Wenn du das kannst, solltest du auch einfach eine neue Version installieren können, oder nicht?
Da fallen mir mehrere Gründe ein:
* Ich möchte meinen Quelltext nicht ändern, wenn es mit der nächsten Version ohne diese Änderungen funktionieren würde und ich nur auf mein eigenen bzw. von mir betreuten Environments achten muss oder die Version 1.2.2x für andere als Requirement festlegen kann.
* Ich möchte über die Update-Möglichkeiten meiner Paketverwaltung informiert werden, wenn eine neue Version des Pakets vorhanden ist. Dazu lasse ich es installiert anstatt es zu deinstallieren und direkt den Quellcode zu verwenden, weil es noch kein Paket für meine Distribution gibt, ich keines machen oder aus einem RPM konvertieren will etc.
Sicher auch nicht der heilige Gral, aber das sind MySQL-spezifische Workarounds über SQL-Kommandos für ältere MySQLdb-Pakete IMHO auch nicht.
Verfasst: Freitag 9. Februar 2007, 13:54
von ebel
Jens schrieb: Aha! Ich frage mich warum er nicht if isinstance(q, unicode) macht...
Hmmm, echt gesagt keine Ahnung
Man kann das natürlich auch so fixen wie Andy Dustman, muss dann aber
vor Zeile 146 in den Quelltext mit in die class BaseCursor einbinden. Wird bei ihm aber erst in Zeile 250 gemacht.
Gruss
ebel
Re: Einfach lösung gefunden für MySQLdb 1.2.1_p2 bug
Verfasst: Freitag 9. Februar 2007, 15:48
von jens
jens hat geschrieben:Ich mache es anders: Ich baue den connect mit "charset=utf8" oder "use_unicode=True" auf. Danach setzte ich den SQL-Befehl "SET NAMES 'utf8';" ab.
Das mit dem "SET NAMES 'utf8';" ist vielleicht doch keine so gute Idee. Zumindest dann nicht, wenn man bestehende DB Daten hat.
Ich hab nämlich eine DB, die per default auf latin1 läuft. Nach dem "SET NAMES 'utf8';" sind die Umlaute defekt.
Ich werde mal versuchen einen DUMP zu ziehen (mit deaktivieren utf8), dann auf utf8 umstellen und den DUMP wieder einspielen... Mal sehen...
EDIT: Ne, das ist ja unfug. Wenn ich z.B. mit phpMyAdmin den dump einspiele, ist ja doch wieder das default encoding aktiv. Also wird der dump wieder in latin1 eingespielt.
Verfasst: Freitag 9. Februar 2007, 18:00
von apollo13
@jens: was das dumpen betrifft: es ist am einfachsten mit phpmyadmin einen dump ziehen, der dir das nicht als datei speichert, sondern anzeigt. Das angezeigte schreibst du dann in eine Datei und speicherst es als Utf-8 ab (charsets die noch im dump rumgurken rauslöschen!). Dann leerst du die db (bzw. drop) und stellst das charset auf utf-8 um. Dann importierst du dein File

Verfasst: Montag 12. Februar 2007, 09:01
von jens
Ja, das Verfahren kenne ich... Aber ich weiß nicht ob ich den PyLucid Nutzer das zumuten sollte
Wenn ich "SET NAMES" nicht in einer neueren Version fest auf 'utf8' stelle, gibt es keine Probleme. Auch wenn der Server evtl. mit latin-1 läuft...
Naja, mal sehen, vielleicht sollte ich das optional machen oder so...
Verfasst: Dienstag 15. Mai 2007, 15:42
von thelittlebug
Bissal spät aber doch :
Du solltest das Encoding auch nachträglich mit "alter table ......" ändern können. Das Encoding lässt sich gesondert einstellen für:
Den ganzen Datenbankserver, wird als default genutzt wenn neue Datenbanken angelegt werden.
Eine Datenbank, wird als default genutzt wenn neue Tabellen angelegt werden.
Eine Tabelle, wird als default genutzt wenn neue Spalten angelegt werden.
Eine Spalte, hier kann nachträglich umgestellt werden wobei dann die DB die Daten konvertiert.
lgherby
p.s. häng auch grad beim Thema MySQL mit SQLAlchemy und Unicode rum. Scheint aber jetzt alles gelöst zu sein.
Verfasst: Dienstag 15. Mai 2007, 16:11
von jens
MySQLdb und encoding... Da gibt es überall Probleme mit, siehe auch:
http://www.python-forum.de/topic-8002.html
In django gibt es auch ein paar Tickets zum Thema... Ich hoffe das alle zukünftigen Versionen vom Modul das besser machen als bisher

Verfasst: Dienstag 15. Mai 2007, 16:48
von thelittlebug
Also Probleme hab ich keine mehr und auch die Lösung war eigentlich sehr angenehm nur hab ich mir zuerst ein paar Unicode Grundlagen durchlesen müssen um zu verstehen wie Python damit umgeht.
Im großen und ganzen habe ich nur folgendes gemacht:
1. SQLAlchemy alle Spalten auch als Unicode deklariert. ( z.b. Unicode(50) )
2. MySQL (war eine bestehende DB) alle Spalten auf utf8_unicode_ci umgestellt. Vorsichtshalber auch die Vorgaben für Tabellen und die DB falls neue Tabellen oder Spalten erstellt werden.
3. Connection String für SQLAlchemy mit den 2 Parametern versehen so wie es auch hier in diesem Thread beschrieben wurde.
4. Templatekonfiguration lt. Mako Doku.
Seitdem klappts auch mit dem bösen Unicode

Teilweise werden einem ja schauerhafte Märchen erzählt, was man nicht alles ersetzen und patchen muss, ich hab nur recht wenig davon mitbekommen.
lgherby
Verfasst: Dienstag 15. Mai 2007, 17:29
von birkenfeld
Die Mär vom "bösen Unicode" kommt daher, dass die Leute weder verstehen, dass Unicodestrings eine Sequenz von Codepoints sind (und nicht etwa "UTF-8-Strings", was man sich darunter auch immer vorstellen soll), noch dass man sich das Leben enorm durch das `codecs`-Modul erleichtern kann.