python - Problem beim Speichern von Unicode-Zeichen in MySQL mit Django

7

Ich habe die Zeichenfolge

%Vor%

Was als

angezeigt werden soll %Vor%

Aber das ist ein anderes Problem. Mein Problem besteht darin, dass ich es in ein Modell einfüge und dann versuche, es in einer Datenbank zu speichern. AKA:

%Vor%

Und ich bekomme:

%Vor%

vollständige Stapelverfolgung (wie angefordert):

%Vor%

Und der wesentliche Teil des Modells:

%Vor%

Ich benutze ein MySQL-Backend mit diesem in meiner settings.py

%Vor%

Also, wie zum Teufel soll ich mit all diesen Unicode-Sachen umgehen? Ich hatte gehofft, es würde alles "nur funktionieren", wenn ich mich von lustigen Zeichensätzen fernhielte und bei UTF8 blieb. Leider scheint es nicht so einfach zu sein.

    
Paul Tarjan 09.07.2009, 08:04
quelle

7 Antworten

12

Danke an alle, die hier gepostet haben. Es hilft wirklich mein Unicode-Wissen (und lernten andere Leute etwas).

Wir schienen alle den falschen Baum zu bellen, da ich versuchte, mein Problem zu vereinfachen und nicht ALLE Informationen zu geben. Es scheint, dass ich nicht "REAL" Unicode-Strings verwendet habe, sondern BeautifulSoup.NavigableString, die sich selbst als Unicode-Strings reprasentieren. So sahen alle Ausdrucke wie Unicode aus, aber sie waren nicht.

Irgendwo tief in der MySQLDB-Bibliothek konnten sie nicht mit diesen Zeichenfolgen umgehen.

Das hat funktioniert:

%Vor%

Auf der anderen Seite:

%Vor%

Aber das funktioniert:

%Vor%

Also, danke nochmal für die Unicode-Hilfe, ich bin mir sicher, dass es sich als nützlich erweisen wird. Aber für jetzt ...

WARNUNG : BeautifulSoup gibt keine REAL Unicode-Strings zurück und sollte mit unicode () erzwungen werden, bevor etwas Sinnvolles mit ihnen gemacht wird.

    
Paul Tarjan 09.07.2009, 20:52
quelle
4

Einige Anmerkungen:

  • Python 2.x hat zwei String-Typen

    • "str", was im Grunde genommen ein Byte-Array ist (damit Sie alles speichern können, was Sie wollen)
    • "Unicode", das ist UCS2 / UCS4-intern Unicode codiert
  • Instanzen dieser Typen werden als "decodierte" Daten betrachtet. Die interne Repräsentation ist die Referenz, also "entschlüsseln" Sie externe Daten darin und "kodieren" Sie in ein externes Format.

  • Eine gute Strategie besteht darin, so früh wie möglich zu dekodieren, wenn Daten in das System gelangen, und so spät wie möglich zu kodieren. Versuchen Sie so oft wie möglich Unicode für die Strings in Ihrem System zu verwenden. (Ich stimme Nikolai in dieser Hinsicht nicht zu).

  • Dieser Kodierungsaspekt trifft auf Nicolais Antwort zu. Er nimmt die ursprüngliche Unicode-Zeichenfolge und codiert sie in utf-8. Aber das löst das Problem nicht (zumindest nicht generell), weil der resultierende Byte-Puffer noch Bytes außerhalb des Bereichs (127) enthalten kann (ich habe das nicht überprüft for \ u2122), was bedeutet, dass Sie dieselbe Ausnahme erneut treffen werden.

  • Immer noch hält Nicolais Analyse, dass Sie eine Unicode-Zeichenfolge übergeben, aber irgendwo im System wird dies als eine Str-Instanz betrachtet. Es reicht aus, wenn die Funktion str () auf Ihr Unicode-Argument angewendet wird.

  • In diesem Fall verwendet Python die sogenannte Standardcodierung, die ascii ist, wenn Sie sie nicht ändern. Es gibt eine Funktion sys.setdefaultencoding, mit der Sie z. utf-8, aber die Funktion ist nur in einem begrenzten Kontext verfügbar, so dass Sie sie nicht einfach im Anwendungscode verwenden können.

  • Mein Gefühl ist das Problem ist irgendwo tiefer in den Schichten, die Sie anrufen. Leider kann ich Django oder MySQL / SQLalchemy nicht kommentieren, aber ich frage mich, ob Sie einen Unicode-Typ angeben könnten, wenn Sie das Attribut 'name' in Ihrem Modell deklarieren. Es wäre gut, wenn DB-Praxis mit Typinformationen auf Feldebene umgehen würde. Vielleicht gibt es eine Alternative zu CharField?!

  • Und ja, Sie können ein einzelnes Anführungszeichen (') in eine doppelt zitierte (") Zeichenkette einbetten und umgekehrt.

ThomasH 09.07.2009 14:22
quelle
3

Sie verwenden Zeichenfolgen vom Typ 'Unicode'. Wenn Ihr Modell oder SQL-Backend diese nicht unterstützt oder nicht in UTF-8 konvertieren kann, führen Sie die Konvertierung einfach selbst aus. Bleibe bei einfachen Strings (python type str) und konvertiere wie in

%Vor%     
Nikolai Ruhe 09.07.2009 08:11
quelle
1

Ich habe gestern daran gearbeitet und festgestellt, dass das Hinzufügen von "charset = utf8" und "use_unicode = 1" zur Verbindungszeichenfolge funktioniert hat (mit SQLAlchemy, denke, es ist das gleiche Problem).

So sieht meine Saite aus: "mysql: // user: pass @ host: 3306 / datenbank? use_unicode = 1 & amp; charset = utf8"

    
klakegg 09.07.2009 08:11
quelle
0

Ich hatte ähnliche Probleme mit mysql und postgres, aber keine Probleme mit sqllite.

So habe ich das Problem mit Postgres gelöst (habe diesen Trick nicht mit mysql getestet, aber ich denke, es würde es auch lösen)

In der Datei, in der Sie mit der Unicode-Zeichenfolge arbeiten, machen Sie ein

%Vor%

und nehme an, dass unistr die Variable ist, die den String enthält, mach ein

%Vor%

in meinem Fall war ich von einer Website schaben

ursprünglicher Code, der Probleme verursachte (ht ist beautifulsoup Gegenstand): -

%Vor%

das Update: -

%Vor%

Ich weiß nicht warum oder was SafeUnicode macht, alles was ich weiß ist, dass es meine Probleme gelöst hat.

    
sajal 09.07.2009 14:42
quelle
0

Ich stimme Nikolai zu. Ich habe bereits Probleme bei der Verwendung von UTF-8, sogar in reinem Python (2.5) gefunden.

Ich habe schließlich die Unicode-Funktion (?) verwendet:

%Vor%

ENCODING war abhängig vom Gebietsschema, wenn ich mich gut erinnere:

%Vor%

Vielleicht werfen Sie einen Blick auf das Python-Unicode-HOWTO ?

    
H_I 09.07.2009 08:33
quelle
-1

Für mich sieht der Apostroph seltsam aus, sollte er nicht so verwackelt werden:

%Vor%     
Key 09.07.2009 08:25
quelle