Umlaut Problem

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Dreiven
User
Beiträge: 6
Registriert: Samstag 10. Juli 2010, 13:45

Hallo,
ich hab ein Problem mit folgendem Szenario:
Ich habe eine Mysql DB die laut phmyadmin mit utf8_unicode kodiert ist.
Dort stehen Umlauten in der Form "Müller" drin.

Das Python Skript läuft auf einem Linux System und soll jetzt ne Abfrage, etwa nach Namen durchführen und das Ergebnis in eine Datei schreiben.
Hierbei hätte ich gerne, die Umlaute zu ü ä ö in der resultierenden Datei selbst umgewandelt.


So jetzt hab ich folgendes Problem, zum einen funktioniert die Abfrage nicht. Wenn ich mir den SQL Befehl mit dem die Abfrage durchgeführt wird, auf der Konsole ausgeben lasse steht da dran Nachname="Müller", also in der Form in der es auch in der DB steht und trotzdem krieg ich nur ein leeres Ergebnis zurück und nicht den entsprechenden Datensatz.

Zudem hab ich es nicht hingebracht, dass Python in den Dateien auch wirklich die Umlaute reinschreibt.


Ausprobiert hab ich schon alles mögliche, sprich im Skript oben z.B. # -*- coding: utf-8 -*- anzugeben, oder auch latin-1 oder iso-8859-1. Und alle möglichen Kombinationen von decode und encode mit den drei Kodierungen.

Ich dachte eigentlich, wenn das mit utf-8 in der DB steht, geb ich in meinem Skript coding: latin-1 an, wende decode('utf_8) auf die entsprechenden Felder an und hab dann meine Umlaute, aber das wirft nur Fehler...


Weiß jemand wie das mit den Umlauten in Python richtig funktioniert, ich bin mit meinem latein (haha) am Ende D:
BlackJack

@Dreiven: In dem Kodierungskommentar am Anfang einer Quelltextdatei muss die Kodierung stehen, die im Quelltext auch tatsächlich verwendet wird. Und die gilt auch nur für literale Unicode-Zeichenketten. Da muss der Compiler ja wissen wie er die Bytes in der Quelltextdatei als Zeichen interpretieren muss.

Wenn Du sagst in der Datenbank stehen die Daten als "Müller" oder es wird Dir Auf der Konsole `Nachname="Müller"` ausgegeben, sagt uns das überhaupt nichts. Zu so einer Ausgabe gehört immer die Information welche Kodierung das Ausgabemedium erwartet hat. Sonst ist das nicht eindeutig. Besser ist es wenn Du die Bytewerte angibst oder bei Zeichenketten (`str`) die `repr()`-Form. Denn nur so weiss man woraus die Daten *tatsächlich* bestehen.
Dreiven
User
Beiträge: 6
Registriert: Samstag 10. Juli 2010, 13:45

Alles klar.
Wenn ich die Daten aus der DB via Repr ausgeben lasse, sieht ein ü so aus u'\xfc'
Und das ü was ich in der Anfrage verwende so '\xc3\xbc'
BlackJack

@Dreiven: Dann solltest Du grundsätzlich mit Unicode-Objekten arbeiten. Das sollte man sowieso tun, wenn man mit Text arbeitet.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

was bei mir mal Probleme bereite hat war ein falsches "Transfer-Encoding", welches in der config-Datei von MySQL stand.

Wenn du z.B. alles in UTF-8 hast, dass Transfer-Encoding aber auf "latin-1" steht, kann das solche Fehler verursachen.

Gruß, noisefloor
BlackJack

@noisefloor: Das 'ü' aus der Datenbank kommt doch anscheinend korrekt als Unicode-Objekt zurück.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

es ist zwar schon länger her bei mir, aber die Transfer-Encoding - die es sowohl fürs Schreiben als auch fürs Lesen gibt - haben bei mir obskure Fehler (= falsche Zeichen) verursacht...

Da ich die Einstellungen der DB seinerzeit nicht ändern konnte, musste ich für das Schreiben alles nach Latin-1 wandeln, damit beim Lesen UTF-8 (ohne weiteres Zutun) rauskam. Wenn ich dass noch richtig im Kopf habe...

Wobei ich nicht sagen will, dass das hier auch der Fehler ist - aber man sollte das mal prüfen.

Besser ist natürlich, wie BlackJack schon sagte, vorm dem Schreiben noch Unicode zu dekodieren und dann nach dem Lesen nach UTF-8 (oder was auch immer zu Encodieren.

Gruß, noisefloor
Dreiven
User
Beiträge: 6
Registriert: Samstag 10. Juli 2010, 13:45

Also versteh ich das richtig, ich soll direkt nach dem Lesen die Strings via .encode('gewünschte kodierung des strings') umwandeln und vor dem schreiben decode('unicode') drauf anwenden?

Ansonsten versteh ich nicht ganz was mit
@Dreiven: Dann solltest Du grundsätzlich mit Unicode-Objekten arbeiten. Das sollte man sowieso tun, wenn man mit Text arbeitet.
gemeint ist.
Hab zwar gegoogled und einige Artikel zu Python/Umlauten/Unicode gelesen, aber so wirklich verstanden hab ich das ganze nicht~~
BlackJack

@Dreiven: Du bekommst von der Datenbank ja anscheinend schon Unicode-Objekte. In Deiner Anfrage, also wahrscheinlich in Deinem Skript stehen aber `str`-"Zeichenketten". Die müssten halt auch Unicode-Objekte sein.
Dreiven
User
Beiträge: 6
Registriert: Samstag 10. Juli 2010, 13:45

Mit der Kombination von, .encode('utf-8') nach dem Auslesen und .decode("latin-1") vor dem befehl absenden , funktioniert das auslesen jetzt und ich krieg ein korrektes Ergebnis zurück.

Meine nächste Frage wäre jetzt, wie ich das Ergebniss kodieren muss, damit es nach schreiben in eine Datei die Umlaute als öäü darstellt.
.encode('latin-1') auf das Ergebnis funktioniert natürlich nicht...
BlackJack

@Dreiven: Das kommt darauf an in welcher Kodierung die Programme die den Text weiterverarbeiten ihn erwarten. Natürlich funktioniert auch 'latin-1' wenn man das haben möchte.

Wobei das mit den unsymmetrischen Kodierungen nicht gut klingt. Wenn das funktioniert ist etwas mit den DB-Einstellungen oder den Daten nicht okay.
Dreiven
User
Beiträge: 6
Registriert: Samstag 10. Juli 2010, 13:45

BlackJack hat geschrieben:@Dreiven: Das kommt darauf an in welcher Kodierung die Programme die den Text weiterverarbeiten ihn erwarten. Natürlich funktioniert auch 'latin-1' wenn man das haben möchte.
Damit wollte ich sagen, dass bei einem .encode('latin-1') versuch Fehler auftreten
Wobei das mit den unsymmetrischen Kodierungen nicht gut klingt. Wenn das funktioniert ist etwas mit den DB-Einstellungen oder den Daten nicht okay.
Ja, ich finds auch sehr merkwürdig und schwer nachvollziehbar.
Könnte das hierran liegen?
Servervariablen und -einstellungen
character set client utf8
(Globaler Wert) latin1
character set connection utf8
(Globaler Wert) latin1
character set results utf8
(Globaler Wert) latin1
collation connection utf8_unicode_ci
(Globaler Wert) latin1_swedish_ci
Aus den "MySQL-System-Variablen"

Wobei ich am Server eh nix ändern darf.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Wenn das funktioniert ist etwas mit den DB-Einstellungen oder den Daten nicht okay.
Genau das meinte ich mit den Transfer-Encodings. So musste ich das bei mir auch lösen, weil ich an der config von MySQL nichts ändern konnte. Warum MySQL per Voreinstellung (bzw. bei mir Ubuntu-Standardinstallation) latin und utf-8 mischt habe ich nie verstanden...

@Dreiven: Man kann mit dem SQL-Befehl "set" diese Parameter überschreiben, ohne die Grundkonfig der DB anzupacken. Musst nur schauen, ob deine Benutzerrechte das hergeben...

Gruß, noisefloor
Dreiven
User
Beiträge: 6
Registriert: Samstag 10. Juli 2010, 13:45

noisefloor hat geschrieben: @Dreiven: Man kann mit dem SQL-Befehl "set" diese Parameter überschreiben, ohne die Grundkonfig der DB anzupacken. Musst nur schauen, ob deine Benutzerrechte das hergeben..
Danke für den Tipp^^
Habs zwar nicht so gelöst, aber das hat mich auf die Lösung gebracht!

Ich kann ja bei MySQLdb.connect() charset und use_unicode einstellen. Bisher war als charset utf8 (das was ja eigentlich die db hat) und use_unicode=True eingestellt.
Jetzt hab ich das ganze auf latin1 und False gestellt und siehe da schon funktionierts und die Umlaute werden korrekt dargestellt!

Und das alles komplett ohne ein einziges .decode/.encode im Code :)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Der server seitige Wert war doch laut Auszug eh schon latin-1. Mich würde nun noch interessieren, ob Du im Script nun Byte-Strings oder Unicode-Strings erhältst!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten