[gelöst]Decoding Problem mit MySQLdb

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
ebel
User
Beiträge: 9
Registriert: Donnerstag 30. März 2006, 17:22

[gelöst]Decoding Problem mit MySQLdb

Beitragvon ebel » Donnerstag 8. Februar 2007, 16:42

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
Zuletzt geändert von ebel am Freitag 9. Februar 2007, 12:02, insgesamt 1-mal geändert.
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Donnerstag 8. Februar 2007, 18:13

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...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beitragvon Y0Gi » Donnerstag 8. Februar 2007, 20:04

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.
ebel
User
Beiträge: 9
Registriert: Donnerstag 30. März 2006, 17:22

Einfach lösung gefunden für MySQLdb 1.2.1_p2 bug

Beitragvon ebel » Freitag 9. Februar 2007, 12:01

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

Code: Alles auswählen

query = query.encode(charset)

austauschen gegen:

Code: Alles auswählen

if isinstance(query, unicode):
    query = query.encode(charset)


Das wars.

Gruss
ebel
Zuletzt geändert von ebel am Freitag 9. Februar 2007, 14:54, insgesamt 1-mal geändert.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beitragvon Y0Gi » Freitag 9. Februar 2007, 12:04

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.
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Re: Einfach lösung gefunden für MySQLdb 1.2.1_p2 bug

Beitragvon jens » Freitag 9. Februar 2007, 12:57

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

Code: Alles auswählen

query = query.encode(charset)

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

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
ebel
User
Beiträge: 9
Registriert: Donnerstag 30. März 2006, 17:22

Re: Einfach lösung gefunden für MySQLdb 1.2.1_p2 bug

Beitragvon ebel » Freitag 9. Februar 2007, 13:06

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
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Freitag 9. Februar 2007, 13:11

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?

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
ebel
User
Beiträge: 9
Registriert: Donnerstag 30. März 2006, 17:22

Neues MySQLdb 1.2.2 Modul installaieren

Beitragvon ebel » Freitag 9. Februar 2007, 13:38

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
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Freitag 9. Februar 2007, 13:40

Aha! Ich frage mich warum er nicht if isinstance(q, unicode) macht...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beitragvon Y0Gi » Freitag 9. Februar 2007, 13:47

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.
ebel
User
Beiträge: 9
Registriert: Donnerstag 30. März 2006, 17:22

Beitragvon ebel » Freitag 9. Februar 2007, 13:54

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

Code: Alles auswählen

from types import UnicodeType

vor Zeile 146 in den Quelltext mit in die class BaseCursor einbinden. Wird bei ihm aber erst in Zeile 250 gemacht.

Gruss
ebel
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Re: Einfach lösung gefunden für MySQLdb 1.2.1_p2 bug

Beitragvon jens » Freitag 9. Februar 2007, 15:48

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.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
apollo13
User
Beiträge: 827
Registriert: Samstag 5. Februar 2005, 17:53

Beitragvon apollo13 » Freitag 9. Februar 2007, 18:00

@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 :)
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Montag 12. Februar 2007, 09:01

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...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd

Wer ist online?

Mitglieder in diesem Forum: Google [Bot]