SQLAlchemy: Umgang mit CP-1252 Daten, wenn Python erwartet, dass es UTF-8 ist

Ich arbeite mit einer vorhandenen SQLite-Datenbank und erlebe Fehler aufgrund der Daten, die in CP-1252 codiert werden, wenn Python erwartet, dass es UTF-8 ist.

>>> import sqlite3 >>> conn = sqlite3.connect('dnd.sqlite') >>> curs = conn.cursor() >>> result = curs.execute("SELECT * FROM dnd_characterclass WHERE id=802") Traceback (most recent call last): File "<input>", line 1, in <module> OperationalError: Could not decode to UTF-8 column 'short_description_html' with text ' <p>Over a dozen deities have worshipers who are paladins, promoting law and good across Faer n, but it is the Weave itself that 

Das beleidigende Zeichen ist \0xfb das zu û decodiert. Andere beleidigende Texte beinhalten “?nd and slay illithids.” die "smart quotes" \0x93 und \0x94 .

SQLite, Python, Unicode und Non-Utf Daten Details, wie dieses Problem gelöst werden kann, wenn mit sqlite3 auf eigene Faust.

Allerdings nutze ich SQLAlchemy. Wie kann ich mit CP-1252 kodierten Daten in einer SQLite-Datenbank umgehen, wenn ich SQLAlchemy verwende?


Bearbeiten:

Dies gilt auch für alle anderen lustigen Kodierungen in einem SQLite TEXT Feld, wie latin-1 , cp437 , und so weiter.

2 Solutions collect form web for “SQLAlchemy: Umgang mit CP-1252 Daten, wenn Python erwartet, dass es UTF-8 ist”

SQLAlchemy und SQLite verhalten sich normal. Die Lösung besteht darin, die Nicht-UTF-8-Daten in der Datenbank zu reparieren.

Ich schrieb die unten, Zeichnung Inspiration von https://stackoverflow.com/a/2395414/1191425 . Es:

  • Lädt die Ziel-SQLite-Datenbank hoch
  • Listet alle Spalten in allen Tabellen auf
  • Wenn die Spalte ein text , clob oder clob Typ ist – einschließlich Varianten wie varchar und longtext – werden die Daten aus dem INPUT_ENCODING auf UTF-8 neu codiert.

 INPUT_ENCODING = 'cp1252' # The encoding you want to convert from import sqlite3 db = sqlite3.connect('dnd_fixed.sqlite') db.create_function('FIXENCODING', 1, lambda s: str(s).decode(INPUT_ENCODING)) cur = db.cursor() tables = cur.execute('SELECT name FROM sqlite_master WHERE type="table"').fetchall() tables = [t[0] for t in tables] for table in tables: columns = cur.execute('PRAGMA table_info(%s)' % table ).fetchall() # Note: pragma arguments can't be parameterized. for column_id, column_name, column_type, nullable, default_value, primary_key in columns: if ('char' in column_type) or ('text' in column_type) or ('clob' in column_type): # Table names and column names can't be parameterized either. db.execute('UPDATE "{0}" SET "{1}" = FIXENCODING(CAST("{1}" AS BLOB))'.format(table, column_name)) 

Nachdem dieses Skript ausgeführt wird, sind alle *text* , *char* und *clob* Felder in UTF-8 und es werden keine Unicode-Decodierungsfehler mehr auftreten. Ich kann jetzt Faerûn nach meinem Herzen zufrieden sein.

Wenn Sie eine Verbindungs-URI haben, können Sie die folgenden Optionen zu Ihrem DB-Verbindungs-URI hinzufügen:

 DB_CONNECTION = mysql+pymysql://{username}:{password}@{host}/{db_name}?{options} DB_OPTIONS = { "charset": "cp-1252", "use_unicode": 1, } connection_uri = DB_CONNECTION.format( username=???, ..., options=urllib.urlencode(DB_OPTIONS) ) 

Angenommen, Ihr SQLLite-Treiber kann diese Optionen behandeln (pymysql kann, aber ich weiß nicht, 100% über sqllite), dann werden Ihre Abfragen zurückgeben Unicode-Strings.

  • Wie richte ich SQLite mit einem Django-Projekt ein?
  • Verwenden von PyQt4 - QTableView mit SQLAlchemy mit QSqlTableModel (oder nicht)
  • Sqlite python sqlite3.OperationalError: Datenbank ist gesperrt
  • Sqlite3.OperationalError: Datenbankdatei kann nicht geöffnet werden
  • Cv2.imdecode immer zurückgeben
  • Filter-Abfrage nach verknüpften Objektschlüssel in SQLAlchemy
  • Verbinden Sie mit Pythons sqlite Modul ist langsamer als es manuell zu tun
  • Verwenden von Alembic API aus dem Anwendungscode
  • Python setzt Datenbankdatensätze in Namedtuple
  • SQlite db remote datei Verbindung
  • Import von CSV in Datenbank mit sqlalchemy
  • Python ist die beste Programmiersprache der Welt.