[gelöst] pySQLite und Umlaute bei Variablenübergabe

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Andy
User
Beiträge: 196
Registriert: Sonntag 1. Januar 2006, 20:12
Wohnort: aus dem hohen Norden....

Montag 24. Juli 2006, 17:53

Hallo Forum!

Ich hab´mal wieder ein Prob. Diesmal mit Umlauten u. pysqlite. Die zahlreichen Infos zum Thema hier im Forum haben mich auch nicht weitergebracht, weil ich keine Strings sondern Variablen-Inhalte an SQLite weitergebe.
Ich habe die Variablen denen ich die Entry-Inhalte übergebe, wie folgt encodiert:

Code: Alles auswählen

        vsnr = self.eSerial.get().encode("cp1252")
        vorname = self.entriesVo.get().encode("cp1252")
        zuname = self.entriesZu.get().encode("cp1252")
        straße = self.entriesSt.get().encode("cp1252")
        hausnr = self.entriesHNr.get().encode("cp1252")
        plz = self.entriesPLZ.get().encode("cp1252")
        ort = self.entriesOr.get().encode("cp1252")
        beruf = self.entriesBe.get().encode("cp1252")
        branche = self.entriesBr.get().encode("cp1252")
        gebdat = self.entriesGe.get().encode("cp1252")
        staatsan = self.entriesSta.get().encode("cp1252")
Würde ich dies (ich hab gelesen, dass man beim auslesen decodieren soll?) wieder decodieren, würde SQLite damit nicht klarkommen, weil es die Daten in UTF-8 haben will. Lasse ich dieses so, wird alles richtig in die DB übernommen.

Es erscheint jedoch folgendes Traceback:

Code: Alles auswählen

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python24\lib\lib-tk\Tkinter.py", line 1345, in __call__
    return self.func(*args)
  File "C:\Dokumente und Einstellungen\Desktop\Antrag.pyw", line 234, in saveexcel
    cur.execute(sql)
OperationalError: Could not decode to UTF-8 column 'straße' with text 'äöü'
Es stört also nur noch dieses Traceback; die Daten werden schon völlig
richtig in die Datenbank übernommen.

Hier noch der restliche SQLite-Teil:

Code: Alles auswählen

# 
# Schreiben 
# 

# Nur zum Testen: Alte Datei vorher loeschen 
        try:
            os.remove("Antragsdaten.s3db")
        except:
            pass 

# Verbindung herstellen 
        conn = sqlite3.connect(
            "Antragsdaten.s3db",
            isolation_level = None, # Autocommit
            )
        cur = conn.cursor()
        
# Tabelle erstellen 
        sql = """
        CREATE TABLE adressen (
          vsnr varchar,
          vorname varchar,
          zuname varchar,
          straße varchar,
          hausnr varchar,
          plz varchar,
          ort varchar,
          beruf varchar,
          branche varchar,
          gebdat varchar,
          staatsan varchar
        )
        """
        cur.execute(sql) 

# Werte in die Tabelle schreiben 
        personen = [
            {"vsnr": vsnr, "vorname": vorname, "zuname": zuname,
             "straße": straße, "hausnr": hausnr, "plz": plz, "ort": ort,
             "beruf": beruf, "branche": branche, "gebdat": gebdat,
             "staatsan": staatsan},
        ]
        sql = """
        INSERT INTO adressen (
            vsnr,
            vorname,
            zuname,
            straße,
            hausnr,
            plz,
            ort,
            beruf,
            branche,
            gebdat,
            staatsan
        )
        VALUES (
            :vsnr,
            :vorname,
            :zuname,
            :straße,
            :hausnr,
            :plz,
            :ort,
            :beruf,
            :branche,
            :gebdat,
            :staatsan
        )
        """
        cur.executemany(sql, personen) 

# Verbindung schliessen 
        cur.close()
        conn.close() 

# 
# Lesen 
# 

# Verbindung herstellen 
        conn = sqlite3.connect("Antragsdaten.s3db") 
        cur = conn.cursor() 

        sql = """
        SELECT
            vsnr, vorname, zuname, straße, hausnr, plz, ort, beruf, branche,
            gebdat, staatsan
        FROM
            adressen
        """
        cur.execute(sql)
        rows = cur.fetchall()
        for row in rows:
            vsnr, vorname, zuname, straße, hausnr, plz, ort, beruf, branche, gebdat, staatsan = row

# Verbindung schliessen 
        cur.close() 
        conn.close()
Ein Code-Beispiel wäre richtig super. Für einen Denkanstoß bin ich jedoch
auch schon dankbar.

Gruß andy
Zuletzt geändert von Andy am Mittwoch 26. Juli 2006, 21:30, insgesamt 1-mal geändert.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Montag 24. Juli 2006, 21:10

Andy hat geschrieben:Umlauten u. pysqlite
Hi Andy!

Vielleicht bringt dich dieser Beitrag weiter:
http://www.python-forum.de/post-39457.html#39457

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Andy
User
Beiträge: 196
Registriert: Sonntag 1. Januar 2006, 20:12
Wohnort: aus dem hohen Norden....

Dienstag 25. Juli 2006, 13:36

gerold hat geschrieben: Hi Andy!

Vielleicht bringt dich dieser Beitrag weiter:
http://www.python-forum.de/post-39457.html#39457

lg
Gerold
:-)
Hallo Gerold!
Deinen Beitrag hatte ich auch schon gelesen. Danke Gerold.

Hatte auch schon stundenlang mit den u-Strings (Du magst die ja so gerne
wenn die in die Hundertste gehen ;o) herumhantiert.

Leider hab ich das dann doch nicht so hinbekommen, weil halt die
Variablen aus den Entry´s mein Problem sind.

Weißt Du oder die anderen hier wie ich es hinbekomme, die Entry´s als
u-Strings abzufangen? Ich meine theoretisch soll ja nicht nur die Eingabe von Strings, sondern auch -,/, etc. möglich sein. Sonst könnte man vielleicht was mit StringVar() anrichten???

Gruss andy[/quote]
bb1898
User
Beiträge: 130
Registriert: Mittwoch 12. Juli 2006, 14:28

Dienstag 25. Juli 2006, 14:50

Andy hat geschrieben:Hallo Forum!

Ich hab´mal wieder ein Prob. Diesmal mit Umlauten u. pysqlite. Die zahlreichen Infos zum Thema hier im Forum haben mich auch nicht weitergebracht, weil ich keine Strings sondern Variablen-Inhalte an SQLite weitergebe.
Ich habe die Variablen denen ich die Entry-Inhalte übergebe, wie folgt encodiert:

Code: Alles auswählen

        vsnr = self.eSerial.get().encode("cp1252")
        vorname = self.entriesVo.get().encode("cp1252")
        zuname = self.entriesZu.get().encode("cp1252")
        straße = self.entriesSt.get().encode("cp1252")
        hausnr = self.entriesHNr.get().encode("cp1252")
        plz = self.entriesPLZ.get().encode("cp1252")
        ort = self.entriesOr.get().encode("cp1252")
        beruf = self.entriesBe.get().encode("cp1252")
        branche = self.entriesBr.get().encode("cp1252")
        gebdat = self.entriesGe.get().encode("cp1252")
        staatsan = self.entriesSta.get().encode("cp1252")
Würde ich dies (ich hab gelesen, dass man beim auslesen decodieren soll?) wieder decodieren, würde SQLite damit nicht klarkommen, weil es die Daten in UTF-8 haben will. Lasse ich dieses so, wird alles richtig in die DB übernommen.
Das passt nicht wirklich zusammen. Wenn das Programm so weit keine Fehlermeldung bringt, dann heißt das: self.entriesVo.get() gibt ein Unicode-Objekt zurück, sonst könnte "encode" nicht darauf angewandt werden. Du wandelst dieses Unicode-Objekt in einen Python-String im Encoding "cp1252" um, also in den gewöhnlichen Windows-Zeichensatz.

Das scheint mir schon mal falsch, wenn SQLite UTF-8 haben will.
Es erscheint jedoch folgendes Traceback:

Code: Alles auswählen

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python24\lib\lib-tk\Tkinter.py", line 1345, in __call__
    return self.func(*args)
  File "C:\Dokumente und Einstellungen\Desktop\Antrag.pyw", line 234, in saveexcel
    cur.execute(sql)
OperationalError: Could not decode to UTF-8 column 'straße' with text 'äöü'
Es stört also nur noch dieses Traceback; die Daten werden schon völlig
richtig in die Datenbank übernommen.
Diese letzte Aussage ist mir einigermassen schleierhaft, denn cur.execute(sql) wird ja gerade nicht ausgeführt. Und zwar m.E. deshalb nicht, weil Du vorher in den falschen Zeichensatz umgewandelt hast.

Meiner Ansicht nach müsste das Ganze funktionieren, wenn Du in allen "encode"-Aufrufen den richtigen Zeichensatz übergibst, also "utf-8" statt "cp1252".

"u-strings" sind nichts anderes als Unicode-Objekte: die Notation erlaubt eine einfache Angabe solcher Objekte als Literale, sonst ist da weiter nichts dahinter.
Andy
User
Beiträge: 196
Registriert: Sonntag 1. Januar 2006, 20:12
Wohnort: aus dem hohen Norden....

Dienstag 25. Juli 2006, 18:13

bb1898 hat geschrieben: Meiner Ansicht nach müsste das Ganze funktionieren, wenn Du in allen "encode"-Aufrufen den richtigen Zeichensatz übergibst, also "utf-8" statt "cp1252".
Hi bb1898!

Insofern hast Du Recht. War ich auch schon drüber gefallen, dass es hier nicht mehr zu einer Fehlermeldung kommt.

Jedoch habe ich dann genau dass selbe Problem, als wenn ich die encodings einfach weglassen würde; die Ausgabe in der SQLite-Datenbank sieht dann nämlich so aus: äöüß (soll heißen äöüß)

Deshalb hatte ich ja schon cp1252 probiert. Tja, warum das Traceback halt sagt, dass cur.execute(sql) nicht ausgeführt wird, kann ich mir auch nicht erklären, in der Datenbank ist dann alles richtig.

Ich weiß net wo dran es liegen kann. :cry:
Hat noch jemand Ratschläge?

Gruss andy
BlackJack

Dienstag 25. Juli 2006, 23:38

Andy hat geschrieben:Jedoch habe ich dann genau dass selbe Problem, als wenn ich die encodings einfach weglassen würde; die Ausgabe in der SQLite-Datenbank sieht dann nämlich so aus: äöüß (soll heißen äöüß)
Was heisst das? Wie überprüfst Du das? Es macht wenig Sinn sich das einfach als Zeichenkette ausgeben zu lassen, man sollte immer die `repr()` Form nehmen, damit man sicher weiss welche Bytes in der Zeichenkette stehen. Bei einer Zeichenkette interpretiert die Shell oder das GUI-Toolkit die Bytes ja auch wieder mit irgendeiner Kodierung.
Andy
User
Beiträge: 196
Registriert: Sonntag 1. Januar 2006, 20:12
Wohnort: aus dem hohen Norden....

Mittwoch 26. Juli 2006, 21:30

BlackJack hat geschrieben: Was heisst das? Wie überprüfst Du das? Es macht wenig Sinn sich das einfach als Zeichenkette ausgeben zu lassen, man sollte immer die `repr()` Form nehmen, damit man sicher weiss welche Bytes in der Zeichenkette stehen. Bei einer Zeichenkette interpretiert die Shell oder das GUI-Toolkit die Bytes ja auch wieder mit irgendeiner Kodierung.
Hallo BlackJack,

Nein, nicht als Zeichenkette. Sondern in SQLite Administrator 0.8.2.5.

Das Problem hat sich hier jedoch gelöst :P :
http://www.python-forum.de/post-41194.html#41194

Mit dem SQLite Database Browser funzt dass nämlich. :lol:

Trotzdem vielen Dank (manchmal geht man beim schreiben halt davon aus, dass es verständlich rüberkommt...sorry) :oops:

Gruss andy
Antworten