Ich dachte du haettest dir die Praesentation schon angeschaut? Du hast es aber scheinbar noch nicht ganz verdaut (es ist - zugegeben - nicht ganz einfach). Also nochmal durcharbeiten!
Python 2 arbeitet mit Byte-Strings, aus der Datenbank bekommst du mit Latin1 kodierte Byte-Strings. Python 2 dekodiert unbekannte Byte-Strings nunmal mit ASCII (in Python 3 mit utf-8). Und Peng!
Damit dein Vorhaben funktioniert, musst du deine Byte-Strings zu Unicode Objekten dekodieren (per `decode` mit dem entsprechenden Encoding.)
AFAIR gibt es zu mysqldb aber auch eine Encoding Option mit der man direkt `unicode` Objekte aus Text-Feldern bekommt.
Formattieren von Nicht-7-bit-Strings
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
- kajarno
- User
- Beiträge: 26
- Registriert: Samstag 16. Januar 2010, 12:41
- Wohnort: München
- Kontaktdaten:
Cofi: wenn Du mit "die Praesentation" http://wiki.python-forum.de/Von%20Umlau ... 0Encodings meinst, ja, ich habe sie gelesen. Auch versucht umzusetzen. Aber die Längen kriege ich nie richtig hin, aus der Datenbank. Encoden und decoden tue ich hier so:cofi hat geschrieben:Ich dachte du haettest dir die Praesentation schon angeschaut? Du hast es aber scheinbar noch nicht ganz verdaut (es ist - zugegeben - nicht ganz einfach). Also nochmal durcharbeiten!
Python 2 arbeitet mit Byte-Strings, aus der Datenbank bekommst du mit Latin1 kodierte Byte-Strings. Python 2 dekodiert unbekannte Byte-Strings nunmal mit ASCII (in Python 3 mit utf-8). Und Peng!
Damit dein Vorhaben funktioniert, musst du deine Byte-Strings zu Unicode Objekten dekodieren (per `decode` mit dem entsprechenden Encoding.)
AFAIR gibt es zu mysqldb aber auch eine Encoding Option mit der man direkt `unicode` Objekte aus Text-Feldern bekommt.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import codecs
import sys
import MySQLdb
db = MySQLdb.connect(host='localhost', user='testuser', passwd='testpw',db="test")
c = db.cursor()
c.execute("select * from umlaute")
selectresult = c.fetchall()
for item in selectresult:
umlautfld = item[0]
print umlautfld, len(umlautfld);
for item in selectresult:
umlautfld = item[0]
s_unicode = umlautfld.decode("iso-8859-1")
s_utf8 = s_unicode.encode("utf-8")
print "types:", type(umlautfld),type(s_unicode), type(s_utf8)
print " len",umlautfld,len(umlautfld),len(s_unicode),len(s_utf8)
Code: Alles auswählen
kaj@Birger[kajtajm]$ umlautbeispiel.py
Gemüse 7
Obst 4
München 8
1¾ 3
Herrlich 8
Wunderbar 9
types: <type 'str'> <type 'unicode'> <type 'str'>
len Gemüse 7 7 9
types: <type 'str'> <type 'unicode'> <type 'str'>
len Obst 4 4 4
types: <type 'str'> <type 'unicode'> <type 'str'>
len München 8 8 10
types: <type 'str'> <type 'unicode'> <type 'str'>
len 1¾ 3 3 5
types: <type 'str'> <type 'unicode'> <type 'str'>
len Herrlich 8 8 8
types: <type 'str'> <type 'unicode'> <type 'str'>
len Wunderbar 9 9 9
Kaj Arnö, Sun VP MySQL Community Relations
Vormals (1979-99) Programmierer, möchte 2010 alte Künste wiederbeleben, und zwar mit PyObjC und MySQLdb unter Mac. Aus Finnland, Muttersprache Schwedisch. Bevorzugt Deutsch über Englisch. In München seit 2006.
Vormals (1979-99) Programmierer, möchte 2010 alte Künste wiederbeleben, und zwar mit PyObjC und MySQLdb unter Mac. Aus Finnland, Muttersprache Schwedisch. Bevorzugt Deutsch über Englisch. In München seit 2006.
- kajarno
- User
- Beiträge: 26
- Registriert: Samstag 16. Januar 2010, 12:41
- Wohnort: München
- Kontaktdaten:
Jens, ja, habe ich probiert (hätte ich sagen sollen). Half auch nicht. Die Daten konnten nicht von Python als Unicode mit richtiger "len("-Berechnung behandelt werden.jens hat geschrieben:Du kannst MySQLdb.connect noch ein paar Einstellungen mit geben wie charset="utf8" und use_unicode=True
Kaj Arnö, Sun VP MySQL Community Relations
Vormals (1979-99) Programmierer, möchte 2010 alte Künste wiederbeleben, und zwar mit PyObjC und MySQLdb unter Mac. Aus Finnland, Muttersprache Schwedisch. Bevorzugt Deutsch über Englisch. In München seit 2006.
Vormals (1979-99) Programmierer, möchte 2010 alte Künste wiederbeleben, und zwar mit PyObjC und MySQLdb unter Mac. Aus Finnland, Muttersprache Schwedisch. Bevorzugt Deutsch über Englisch. In München seit 2006.
Vielleicht solltest Du auch mal ausgeben was die Zeichen- bzw. Byteketten *wirklich* enthalten, also mit `repr()` damit es keine Rolle spielt was die Anwendung die das darstellt, erwartet und interpretiert. Für mich sieht das so aus, als wenn Du aus der Datenbank `str`, also Byteketten, in UTF-8 Kodierung bekommst. Und dann stimmen die Längen die da stehen. "Gemüse" hat UTF-8-kodiert eine Länge von 7 Bytes. Wenn man diese als ISO-8851-1 dekodiert bekommt man 7 Unicode-Zeichen. Da sind zwei die nicht von ASCII abgedeckt werden, das werden dann also als UTF-8 kodiert 9 Bytes.
Code: Alles auswählen
In [48]: s
Out[48]: 'Gem\xc3\xbcse'
In [49]: len(s)
Out[49]: 7
In [50]: print s
Gemüse
In [51]: u = s.decode('iso-8859-1')
In [52]: u
Out[52]: u'Gem\xc3\xbcse'
In [53]: len(u)
Out[53]: 7
In [54]: print u
Gemüse
In [55]: s2 = u.encode('UTF-8')
In [56]: s2
Out[56]: 'Gem\xc3\x83\xc2\xbcse'
In [57]: len(s2)
Out[57]: 9
In [58]: print s2
Gemüse
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Nein, Cofi meinte die Präsentation mit den richtigen Folien, als PDF.kajarno hat geschrieben:Cofi: wenn Du mit "die Praesentation" http://wiki.python-forum.de/Von%20Umlau ... 0Encodings meinst, ja, ich habe sie gelesen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Die hier (Die hat acuh schon Hyperion gepostet - im 5. Post dieses Threads)Leonidas hat geschrieben:Nein, Cofi meinte die Präsentation mit den richtigen Folien, als PDF.
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
- kajarno
- User
- Beiträge: 26
- Registriert: Samstag 16. Januar 2010, 12:41
- Wohnort: München
- Kontaktdaten:
Danke! Jetzt gelesen. Ist komplizierter als erwünscht. "Man kann das Encoding nicht zuverlässig erraten", nicht gerade ermutigend.cofi hat geschrieben:Die hier (Die hat acuh schon Hyperion gepostet - im 5. Post dieses Threads)Leonidas hat geschrieben:Nein, Cofi meinte die Präsentation mit den richtigen Folien, als PDF.
Also habe ich die Lösung selbst gebastelt, denn eigentlich ist alles was ich brauche eine Funktion, die die *Druckbreite* eines Strings errechnet, anstatt die Speicherbreite (die beim Drucken herzlich egal ist).
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import MySQLdb
db = MySQLdb.connect(host='localhost', user='testuser', passwd='testpw',db="test")
c = db.cursor()
c.execute("select * from umlaute")
selectresult = c.fetchall()
for item in selectresult:
umlautfld = item[0]
iUmlaute = 0
for zeichen in umlautfld:
if ord(zeichen) < 48 or ord(zeichen) > 122:
iUmlaute += 1
iUmlaute = iUmlaute / 2
druckbreite = len(umlautfld) - iUmlaute
umlautfld += " " * (9-druckbreite)
print umlautfld, druckbreite, "Nicht schief"
Code: Alles auswählen
kaj@Birger[kajtajm]$ umlautbeispiel.py
Gemüse 6 Nicht schief
Obst 4 Nicht schief
München 7 Nicht schief
1¾ 2 Nicht schief
Herrlich 8 Nicht schief
Wunderbar 9 Nicht schief
Kaj Arnö, Sun VP MySQL Community Relations
Vormals (1979-99) Programmierer, möchte 2010 alte Künste wiederbeleben, und zwar mit PyObjC und MySQLdb unter Mac. Aus Finnland, Muttersprache Schwedisch. Bevorzugt Deutsch über Englisch. In München seit 2006.
Vormals (1979-99) Programmierer, möchte 2010 alte Künste wiederbeleben, und zwar mit PyObjC und MySQLdb unter Mac. Aus Finnland, Muttersprache Schwedisch. Bevorzugt Deutsch über Englisch. In München seit 2006.
@kajarno: Das ist ziemlicher Murks, Du solltest wirklich lieber versuchen zu *verstehen* wie das mit Unicode funktioniert. Denn in aller Regel ist die Länge einer Unicode-Zeichenkette, zumindest in unseren Breitengraden (und wenn es nicht gerade um MacOS' Dateinamen geht), auch die Anzahl der Zeichen, die ausgegeben werden.
In Deinem Fall muss man die Kodierung nicht erraten, denn Du weisst ja in welcher Kodierung Du die Daten in die Datenbank steckst und in welcher Du sie heraus bekommst. Also *Du* weisst das jetzt nicht, aber das ist etwas das man wissen *sollte*. Wenn ich mir die `mysql`-Sitzung weiter oben anschaue, die ja wohl in einem Terminal eingegeben wurde, das UTF-8 "spricht", dann würde ich mal darauf tippen, dass die Daten als UTF-8 in der DB stehen. Du gehst aber aus irgendeinem Grund davon aus, dass es Latin1 ist!? Warum? Wenn die DB auch davon ausgeht, dann liefert sie natürlich auch falsche Daten wenn Du sagst Du möchtest das Latin1, was keines ist, als Unicode-Objekte haben.
In Deinem Fall muss man die Kodierung nicht erraten, denn Du weisst ja in welcher Kodierung Du die Daten in die Datenbank steckst und in welcher Du sie heraus bekommst. Also *Du* weisst das jetzt nicht, aber das ist etwas das man wissen *sollte*. Wenn ich mir die `mysql`-Sitzung weiter oben anschaue, die ja wohl in einem Terminal eingegeben wurde, das UTF-8 "spricht", dann würde ich mal darauf tippen, dass die Daten als UTF-8 in der DB stehen. Du gehst aber aus irgendeinem Grund davon aus, dass es Latin1 ist!? Warum? Wenn die DB auch davon ausgeht, dann liefert sie natürlich auch falsche Daten wenn Du sagst Du möchtest das Latin1, was keines ist, als Unicode-Objekte haben.
Wie BlackJack schon schrieb, lass das lieber und versuch zu verstehen, wie das mit den Zeichenkodierungen funktioniert, sonst wirst du bestimmt bald wieder irgendwelche Probleme kriegen.kajarno hat geschrieben:Also habe ich die Lösung selbst gebastelt, denn eigentlich ist alles was ich brauche eine Funktion, die die *Druckbreite* eines Strings errechnet, anstatt die Speicherbreite (die beim Drucken herzlich egal ist).
Die Druckbreite zu bestimmen ist übrigens wirklich nicht so einfach.
Code: Alles auswählen
>>> ae = unicodedata.normalize("NFD", u"ä")
>>> print ae, len(ae), repr(ae)
ä 2 u'a\u0308'
- kajarno
- User
- Beiträge: 26
- Registriert: Samstag 16. Januar 2010, 12:41
- Wohnort: München
- Kontaktdaten:
Darii, BlackJack: Ich glaube nicht dass ich das Thema Unicode jetzt für immer los geworden bin! Die momentane Frustration darüber, dass eine einfache Sache wie die Berechnung der Breite einer Zeichenkette mein Fortschritt verhindert, habe ich allerdings überwunden.
Die Datenbank ist in latin1 weil das auch so von MySQL gemeldet wird (steht oben in einem code-Abschnitt). Eines Tages könnte ich versuchen, die Daten mit UTF-8 in MySQL anzulegen. Dann befürchte ich, später mal Probleme bei der Dateneingabe direkt unter MySQL, bzw. mit der Kommunikation mit Flatfiles zu bekommen, das alles bereiche sind, wo es heute problemlos läuft.
Zum Experimentieren um die richtige Lösung zu finden bin ich hoffentlich bei dem nächsten Unicode-Problem bereit.
Breite von "ä": Huch, wenn len("ä") = 2 auch wenn man alles "richtig" eingibt, ist ja komisch. In den Breitengraden aus denen ich komme (Finnland, Schweden usw.) ist "ä" ein (1) Buchstabe und keineswegs ein "zusammengesetztes Zeichen" oder irgendeine Spezialform von "a" (wie es hier südlich vom Ostsee der Fall zu sein scheint). "ä" kommt sortiermäßig auch nach "z" (... xyzåäö). Also würde in diesem Falle die "richtige" Lösung überhaupt nicht die tatsächlich richtige Lösung sein, zumindest aus meiner Sicht (locale).
Die Datenbank ist in latin1 weil das auch so von MySQL gemeldet wird (steht oben in einem code-Abschnitt). Eines Tages könnte ich versuchen, die Daten mit UTF-8 in MySQL anzulegen. Dann befürchte ich, später mal Probleme bei der Dateneingabe direkt unter MySQL, bzw. mit der Kommunikation mit Flatfiles zu bekommen, das alles bereiche sind, wo es heute problemlos läuft.
Zum Experimentieren um die richtige Lösung zu finden bin ich hoffentlich bei dem nächsten Unicode-Problem bereit.
Breite von "ä": Huch, wenn len("ä") = 2 auch wenn man alles "richtig" eingibt, ist ja komisch. In den Breitengraden aus denen ich komme (Finnland, Schweden usw.) ist "ä" ein (1) Buchstabe und keineswegs ein "zusammengesetztes Zeichen" oder irgendeine Spezialform von "a" (wie es hier südlich vom Ostsee der Fall zu sein scheint). "ä" kommt sortiermäßig auch nach "z" (... xyzåäö). Also würde in diesem Falle die "richtige" Lösung überhaupt nicht die tatsächlich richtige Lösung sein, zumindest aus meiner Sicht (locale).
Darii hat geschrieben:Wie BlackJack schon schrieb, lass das lieber und versuch zu verstehen, wie das mit den Zeichenkodierungen funktioniert, sonst wirst du bestimmt bald wieder irgendwelche Probleme kriegen.kajarno hat geschrieben:Also habe ich die Lösung selbst gebastelt, denn eigentlich ist alles was ich brauche eine Funktion, die die *Druckbreite* eines Strings errechnet, anstatt die Speicherbreite (die beim Drucken herzlich egal ist).
Die Druckbreite zu bestimmen ist übrigens wirklich nicht so einfach.Ein druckbares Zeichen kann nämlich durchaus aus mehreren Zeichen zusammengesetzt sein.Code: Alles auswählen
>>> ae = unicodedata.normalize("NFD", u"ä") >>> print ae, len(ae), repr(ae) ä 2 u'a\u0308'
Kaj Arnö, Sun VP MySQL Community Relations
Vormals (1979-99) Programmierer, möchte 2010 alte Künste wiederbeleben, und zwar mit PyObjC und MySQLdb unter Mac. Aus Finnland, Muttersprache Schwedisch. Bevorzugt Deutsch über Englisch. In München seit 2006.
Vormals (1979-99) Programmierer, möchte 2010 alte Künste wiederbeleben, und zwar mit PyObjC und MySQLdb unter Mac. Aus Finnland, Muttersprache Schwedisch. Bevorzugt Deutsch über Englisch. In München seit 2006.
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Das hat nicht sonderlich viel mit locales zu tun, sondern mit dem Unicode-Standard, der eben verschiedene Normalformen definiert. Je nachdem ist ä eben ein Kompisitum aus a und Diaeresis(Combining Diaeresis) oder ein einzelner Buchstabe(a with Diaeresis).kajarno hat geschrieben:In den Breitengraden aus denen ich komme (Finnland, Schweden usw.) ist "ä" ein (1) Buchstabe und keineswegs ein "zusammengesetztes Zeichen" oder irgendeine Spezialform von "a" (wie es hier südlich vom Ostsee der Fall zu sein scheint).
Aber das kann die Doku viel besser als ich: http://docs.python.org/library/unicoded ... .normalize
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
@kajarno: Was die Datenbank annimmt welche Kodierung sie bekommt, und welche sie tatsächlich bekommt, sind zwei verschiedene Dinge. Und ich denke Du hast da falsche/kaputte Daten in der DB. Du sagtest ja selbst, dass MySQL die Länge auch "falsch" berechnet. Was höchstwahrscheinlich daran liegt, das in der DB die "denkt" Latin1 zu enthalten, tatsächlich UTF-8 drin ist.
Wenn eine Datenbank/Tabelle auf Latin1 eingestellt ist, müssen die Daten auch so kodiert da reingeschrieben werden. Man kann allerdings auch problemlos UTF-8 kodierte Umlaute in so eine Tabelle schreiben, weil das ja in Latin1 keine illegallen Bytefolgen sind. Sie bedeuten halt nur etwas anderes, aber das weis die Datenbanksoftware ja nicht.
Wenn eine Datenbank/Tabelle auf Latin1 eingestellt ist, müssen die Daten auch so kodiert da reingeschrieben werden. Man kann allerdings auch problemlos UTF-8 kodierte Umlaute in so eine Tabelle schreiben, weil das ja in Latin1 keine illegallen Bytefolgen sind. Sie bedeuten halt nur etwas anderes, aber das weis die Datenbanksoftware ja nicht.
Das mit der Normalform war auch nur ein Beispiel(wenn auch ein wichtiges, denn OSX kodiert seine Dateinamen so und kommt leider mit anders kodierten nicht zurecht). Er gibt im Grunde genommen nur eine sichere Methode herauszufinden wie „breit“ ein String ist: Rendern lassen und gucken was dabei rauskommt. Alles andere führt zwangläufig zu Fehlern.kajarno hat geschrieben:Breite von "ä": Huch, wenn len("ä") = 2 auch wenn man alles "richtig" eingibt, ist ja komisch. In den Breitengraden aus denen ich komme (Finnland, Schweden usw.) ist "ä" ein (1) Buchstabe und keineswegs ein "zusammengesetztes Zeichen" oder irgendeine Spezialform von "a" (wie es hier südlich vom Ostsee der Fall zu sein scheint).
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Mach doch mal sowas:
Ich hab auch einen einfachen Test geschrieben bei dem ich mit unichr() einen Test string in unicode erzeuge. Der wird dann in die Datenbank eingefügt und gleich wieder herraus geholt und mit dem Original verglichen.
Code: Alles auswählen
MYSQL_ENCODING_VARS = ("character_set_server", "character_set_connection", "character_set_results", "collation_connection",)
for var_name in MYSQL_ENCODING_VARS:
cursor.execute("SHOW VARIABLES LIKE %s;", (var_name,))
print var_name, cursor.fetchall()