Text Feld und Unicode

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Ich habe mal wieder ein klassisches Problem: Unicode. Ich habe eine Tabelle mit Unicode() Felder und mit Text() Feldern. Alles, was auch den Unicode() Feldern kommt wie erwartet, alles, was aus den Text() Feldern kommt macht Probleme, obwohl Byte für Byte das gleiche drin steht und auch sonst im gesamten Code identisch behandelt wird. Offensichtlich behandelt Elixir die Text Felder als normale ASCII Felder.

Kann ich Elixir irgendwie dazu überreden, die Text Felder genauso zu behandeln wie Unicode Felder? Geht das über "collation"? Wenn ich das hier versuche bekomme ich nur Fehlermeldungen. Wenn ich statt Text() auch da Unicode() verwende funktioniert alles (zumindest auf den ersten Blick)
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

burli hat geschrieben:Ich habe mal wieder ein klassisches Problem: Unicode. Ich habe eine Tabelle mit Unicode() Felder und mit Text() Feldern. Alles, was auch den Unicode() Feldern kommt wie erwartet, alles, was aus den Text() Feldern kommt macht Probleme, obwohl Byte für Byte das gleiche drin steht und auch sonst im gesamten Code identisch behandelt wird. Offensichtlich behandelt Elixir die Text Felder als normale ASCII Felder.
Was denn für Probleme? Wieso verwendest Du überhaupt "Text"?
burli hat geschrieben: Kann ich Elixir irgendwie dazu überreden, die Text Felder genauso zu behandeln wie Unicode Felder?
convert_unicode=True sollte das bewirken.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Ok, ich dreh gleich völlig am Rad. Ich hab folgendes Model:

Code: Alles auswählen

class Article(Entity):
    using_options(tablename="articles")

    old_id = Field(Integer)
    artno = Field(Integer, unique=True)
    match = Field(Unicode(30), unique=True)
    visible = Field(Boolean, default=True)
    created = Field(DateTime, default=datetime.datetime.now())
    last_update = Field(DateTime, default=datetime.datetime.now())
    de_name = Field(Text)
    en_name = Field(Text)
    de_teaser = Field(Text)
    en_teaser = Field(Text)
    de_desc = Field(Text)
    en_desc = Field(Text)
Das einzig interessante Feld ist im Moment "match". Das dient mir bei einer Flask Webseite als URL. Funktioniert alles prächtig. Aber jetzt kommts. Sobald ich im Model "Field(Text)" gegen "Field(Unicode()) austausche funktioniert es nicht mehr. Dabei haben die Felder nicht das geringste mit der Seite zu tun. Sobald das Feld de_name Unicode ist und etwas drin steht funktioniert die ganze Seite nicht mehr.

Ich bin hier echt gerade völlig ab abdrehen. Das Feld hat mit der Anwendung noch überhaupt nichts zu tun außer dass es vorhanden ist. Es wird an keiner Stelle genutzt. Aber es kommt dann zu solchen Fehlermeldungen http://paste.pocoo.org/show/324481/
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

burli hat geschrieben:Sobald ich im Model "Field(Text)" gegen "Field(Unicode()) austausche funktioniert es nicht mehr.
Du musst auch die Klasse übergeben, nicht eine Instanz!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Du meinst Unicode()? Da gehört noch eine Zahl rein. Bei Text wird nichts angegeben und die Klammer weggelassen. (Siehe Tutorial)

Aber egal wie, die Felder haben nichts, aber auch GAR NICHTS mit der Programmfunktion zu tun. Aber sobald die mit Unicode codiert sind (ich habe auch gerade noch UnicodeText ausprobiert) funktioniert es nicht mehr und ich sehe auch keinen Zusammenhang mit den Stellen im Code, an dem der Fehler angeblich auftreten soll. Oder seit wann stört sich eine for Schleife an der Zeichencodierung?
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

burli hat geschrieben:Du meinst Unicode()? Da gehört noch eine Zahl rein. Bei Text wird nichts angegeben und die Klammer weggelassen. (Siehe Tutorial)
Stimmt!
Aber egal wie, die Felder haben nichts, aber auch GAR NICHTS mit der Programmfunktion zu tun. Aber sobald die mit Unicode codiert sind (ich habe auch gerade noch UnicodeText ausprobiert) funktioniert es nicht mehr und ich sehe auch keinen Zusammenhang mit den Stellen im Code, an dem der Fehler angeblich auftreten soll. Oder seit wann stört sich eine for Schleife an der Zeichencodierung?
Naja, Du wirst irgend wo auf dieses Feld zugreifen. Und dabei kommt es dann wohl zu dem Fehler. Ich denke so kommt man da nicht wirklich weiter. Prinzipiell steht in dem Feld wohl etwas drin, was nicht mit dem angegebenen Encoding dekodiert werden kann. Also schau doch einfach mal in das entsprechende Feld rein?

Evtl. legst Du die Datenbank auch mal neu an; schließlich hast Du ja am Mapping etwas geändert; evtl. stört sich SQLAlchemy daran?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Ich generiere jedesmal die Datenbank komplett neu. Ich habe extra eine Import Routine geschrieben.

Ich greife definitiv nicht auf die Felder zu, nur auf die Objekte. Der Fehler tritt immer dann auf, wenn ich eine Liste mit Objekten durchlaufe (ohne auf die Felder zuzugreifen).

Ich bin aber gerade einen Schritt weiter gekommen. Das Problem tritt in folgendem Stück Code auf, und zwar genau genommen in der zweiten der drei Zeilen

Code: Alles auswählen

    for tag in tags:
        for t in tag.articles:
            lists[cnt].append(t)
Offensichtlich werden Zeichen in die Datenbank geschrieben, die nicht zu UTF-8 passen. Wenn das der Fall ist, hängt sich Python auf, sobald es mit den Objekten zu tun bekommt, selbst wenn das Programm gar nicht direkt auf die Felder zugreift.

Wenn ich jetzt die Felder als UnicodeText definiere und beim Erstellen der Datenbank vor dem Schreiben folgende (und nur diese) magische Zeilen verwende funktioniert das Programm wieder

Code: Alles auswählen

        arts.de_name = arts.de_name.decode("iso-8859-1").encode('utf-8')
        arts.en_name = arts.en_name.decode("iso-8859-1").encode('utf-8')
Wenn also in einem Unicode String in einem Zeichen ein Wert größer 128 steht bekommt Python ein Problem, selbst wenn auf den String im Programmcode gar nicht direkt zugegriffen wird. So zumindest meine Interpretation
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

burli hat geschrieben: Wenn also in einem Unicode String in einem Zeichen ein Wert größer 128 steht bekommt Python ein Problem, selbst wenn auf den String im Programmcode gar nicht direkt zugegriffen wird. So zumindest meine Interpretation
Natürlich wird darauf intern zugegriffen! Das Objekt wird ja schließlich irgend wie angelegt.

Als erstes solltest Du jetzt mal checken, als was die Daten vorliegen. Ich vermute die kommen doch aus Deiner import-Routine? Wieso sind sie dann an dieser Stelle im Code iso-8859-1 codiert? Wieso sind die nicht bereits unicode? Und wieso willst Du sie explizit dann utf-8 codieren? Das erledigt doch SQLAlchemy für dich...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Hyperion hat geschrieben:
burli hat geschrieben: Wenn also in einem Unicode String in einem Zeichen ein Wert größer 128 steht bekommt Python ein Problem, selbst wenn auf den String im Programmcode gar nicht direkt zugegriffen wird. So zumindest meine Interpretation
Natürlich wird darauf intern zugegriffen! Das Objekt wird ja schließlich irgend wie angelegt.
Naja, in einer for Schleife? Darauf muss man erstmal kommen
Hyperion hat geschrieben: Als erstes solltest Du jetzt mal checken, als was die Daten vorliegen. Ich vermute die kommen doch aus Deiner import-Routine? Wieso sind sie dann an dieser Stelle im Code iso-8859-1 codiert? Wieso sind die nicht bereits unicode? Und wieso willst Du sie explizit dann utf-8 codieren? Das erledigt doch SQLAlchemy für dich...
Tja, irgendwie wohl nicht. Und ich hab alles durchprobiert. Die Daten liegen in einer Textdatei. Die habe ich hin und her konvertiert. Desshalb bin ich ja daran so verzweifelt.

Aber es läuft jetzt alles. Das einzige. was ich nicht verstehe ist, wieso die Tabellen nicht als utf-8 angelegt werden sondern in so einem Windows Format (nicht ISO-8859)
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

burli hat geschrieben:
Hyperion hat geschrieben: Natürlich wird darauf intern zugegriffen! Das Objekt wird ja schließlich irgend wie angelegt.
Naja, in einer for Schleife? Darauf muss man erstmal kommen
Das weiß ich doch nicht. Ich kenne den Code ja nicht. Vielleicht habe ich Dich auch falsch verstanden. Fakt ist, dass Du doch Mapping-Objekte hast. Diese werden doch irgend wann irgendwie angelegt. Und dabei dürfte eben etwas schief laufen.
Hyperion hat geschrieben: Als erstes solltest Du jetzt mal checken, als was die Daten vorliegen. Ich vermute die kommen doch aus Deiner import-Routine? Wieso sind sie dann an dieser Stelle im Code iso-8859-1 codiert? Wieso sind die nicht bereits unicode? Und wieso willst Du sie explizit dann utf-8 codieren? Das erledigt doch SQLAlchemy für dich...
Tja, irgendwie wohl nicht. Und ich hab alles durchprobiert.
Ich glaube da liegt vor allem das Problem ;-) Du musst da schon präzise Arbeiten und Dir genau überlegen, wann Du IO-Operationen hast und wie Du dann die Daten behandelst. Wir hatten das Thema Unicode vs. bytestring ja schon häufiger, aber generell gilt eben der Grundsatz: Möglichst früh in Unicode wandeln bei Eingabe Operationen. Und da wird wohl bei Dir etwas schief laufen!
Die Daten liegen in einer Textdatei. Die habe ich hin und her konvertiert. Desshalb bin ich ja daran so verzweifelt.
Siehste, das bringt ja nix. Du musst schon wissen, in welcher Codierung diese Datei vorliegt. Und dann musst Du ja nicht die datei konvertieren, sondern beim Einlesen den Inhalt decodieren.
Aber es läuft jetzt alles. Das einzige. was ich nicht verstehe ist, wieso die Tabellen nicht als utf-8 angelegt werden sondern in so einem Windows Format (nicht ISO-8859)
Was für Tabellen? In einer DB? Welche Datenbank verwendest Du denn?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Hyperion hat geschrieben: Das weiß ich doch nicht. Ich kenne den Code ja nicht. Vielleicht habe ich Dich auch falsch verstanden. Fakt ist, dass Du doch Mapping-Objekte hast. Diese werden doch irgend wann irgendwie angelegt. Und dabei dürfte eben etwas schief laufen.
Naja, die Daten kommen ja auch klaglos in die Datenbank rein. Es muss da in dieser Schleife irgend eine Funktion aufgerufen werden, die sich daran stört.
Was für Tabellen? In einer DB? Welche Datenbank verwendest Du denn?
Leider im Moment MySQL. Wird aber, sobald die Import Orgie abgeschlossen ist, auf Postgresql umgestellt
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

burli hat geschrieben:
Hyperion hat geschrieben: Das weiß ich doch nicht. Ich kenne den Code ja nicht. Vielleicht habe ich Dich auch falsch verstanden. Fakt ist, dass Du doch Mapping-Objekte hast. Diese werden doch irgend wann irgendwie angelegt. Und dabei dürfte eben etwas schief laufen.
Naja, die Daten kommen ja auch klaglos in die Datenbank rein.
Dennoch kann die Ursache für den späteren Fehler doch trotzdem beim Anlegen passieren! Wie speicherst Du die Daten denn? Übergibst Du sie als Unicode oder als Bytestring? Und wenn letzteres mit welcher Codierung?

Die Codierung muss ja von SQLAlchemy dann entsprechend der DB gewählt werden, sprich es kommt ja dann auch noch darauf an, welches Encoding MySQL in dieser Datenbank für Inhalte vorsieht.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Naja, wie ich weiter oben schon geschrieben habe:
burli hat geschrieben:Aber es läuft jetzt alles.
Ich bin inzwischen einen Schritt weiter. Ich habe alle Daten zusammen gesammelt, die ich brauche, habe alles gemeinsam in eine Datenbank gespeichert und zur besseren Bearbeitung wieder in eine XML Datei exportiert. Beim Export werden jetzt halt alle Zeichen escaped. Aber damit kann ich denke ich leben.

Falls sich jemand fragt, warum der ganze Aufwand: ich habe verschiedene Datensätze aus verschiedenen Quellen, die ich zusammenführen musste und irgendwie in eine gut editierbare Form bringen wollte. Gut editierbar heißt in dem Fall Textdatei. Jetzt hab ich alle Daten beisammen, kann sie überarbeiten und anschließend wieder in eine Datenbank einspielen.
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

burli hat geschrieben:Naja, wie ich weiter oben schon geschrieben habe:
burli hat geschrieben:Aber es läuft jetzt alles.
Naja, wenn Dir das reicht ;-)
burli hat geschrieben: Beim Export werden jetzt halt alle Zeichen escaped. Aber damit kann ich denke ich leben.
Hu? Inwiefern "escaped"?
burli hat geschrieben: Falls sich jemand fragt, warum der ganze Aufwand: ich habe verschiedene Datensätze aus verschiedenen Quellen, die ich zusammenführen musste und irgendwie in eine gut editierbare Form bringen wollte. Gut editierbar heißt in dem Fall Textdatei. Jetzt hab ich alle Daten beisammen, kann sie überarbeiten und anschließend wieder in eine Datenbank einspielen.
Also importierst Du erst aus verschiedenen Quellen in eine DB, exportierst dann (mit verstümmelten Zeichen?) und importierst dann wieder in eine DB? Da stimmt doch was nicht :D
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Nein, nicht mehr verstümmelt. Sondern in HTML Schreibweise umgewandelt.

Code: Alles auswählen

Pr&#228;zisionssockel mit gedrehten Kontakten<br>&#13;
Raster 7,62mm<br>&#13;
Ich weiß, klingt komisch, die Aktion. Ich wüsste aber keinen anderen Weg. Der Import hat ja jetzt vollständig funktioniert. Jetzt wird MySQL raus geworfen und alles in eine Postgresql Datenbank importiert. Da wird alles fein säuberlich angelegt. und gewartet.

Den nochmaligen Export in eine XML Datei habe ich deshalb gewählt, weil ich die Daten jetzt noch ergänzen muss, und das geht in dem Fall in einer Textdatei besser als in einer Datenbank mit GUI oder was auch immer.
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

burli hat geschrieben:Nein, nicht mehr verstümmelt. Sondern in HTML Schreibweise umgewandelt.

Code: Alles auswählen

Pr&#228;zisionssockel mit gedrehten Kontakten<br>&#13;
Raster 7,62mm<br>&#13;
Den nochmaligen Export in eine XML Datei habe ich deshalb gewählt, weil ich die Daten jetzt noch ergänzen muss, und das geht in dem Fall in einer Textdatei besser als in einer Datenbank mit GUI oder was auch immer.
Naja, manuelles Escapen geht nicht wirklich gut von der Hand :twisted:

Dann achte aber jetzt bitte darauf, dass Du konsequent auf Unicode setzt intern und bei Postgres am besten utf-8 als Encoding einstellst. Damit vermeidest Du Probleme in der Zukunft und brauchst so einen dirty workaround nicht ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Die Bereiche, die ich bearbeiten muss, gehen glücklicherweise ohne Sonderzeichen.

Ab sofort läuft alles nur noch in einer Postgresql Datenbank. Da werde ich schon darauf achten, dass alles über UTF-8 läuft
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

burli hat geschrieben:Ab sofort läuft alles nur noch in einer Postgresql Datenbank. Da werde ich schon darauf achten, dass alles über UTF-8 läuft
Aber intern bitte dennoch mit Unicode!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Uhm, du hast in deiner Datenbank HTML-Entities in deinem Text? Das ist auch jeden Fall etwas was man vermeiden sollte. phpBB macht es in der Hinsicht aber ganz ähnlich falsch :roll:
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Leonidas hat geschrieben:Uhm, du hast in deiner Datenbank HTML-Entities in deinem Text? Das ist auch jeden Fall etwas was man vermeiden sollte. phpBB macht es in der Hinsicht aber ganz ähnlich falsch :roll:
Nein, nur in der XML Datei. In der Datenbank stehen normale Zeichen. Das wurde nur von dem XML Export umgewandlet. Beim Import von XML in die Datenbank hab ich sichergestellt, dass in der Datenbank normale Zeichen angekommen sind. Da steht also äöüßµ usw auch genau so drin
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Antworten