PyGreSQL und Sonderzeichen

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
ullat
User
Beiträge: 3
Registriert: Mittwoch 18. Juli 2007, 14:14

Hallo Forum,

wie kann man Sonderzeichen, wie z.B. Umlaute per Python und PyGreSQL in die PostgreSQL Datenbank bekommen?

Ich habe folgendes Verhalten:

Code: Alles auswählen

>>> conn.query("SELECT * FROM A1339 WHERE NAME = 'Schweiz'")
<pg query result>
>>> conn.query("SELECT * FROM A1339 WHERE NAME = 'Österreich'")

Traceback (most recent call last):
  File "<pyshell#32>", line 1, in -toplevel-
    conn.query("SELECT * FROM A1339 WHERE NAME = 'Österreich'")
ProgrammingError: ERROR:  invalid byte sequence for encoding "UNICODE": 0xd673
Der Versuch vorab den String in Unicode umzuwandeln misslang, da die query-Funktion einen String und kein Unicode erwartet.

Code: Alles auswählen

unicode("Österreich", "latin-1") 
Ich bin für jede Hilfe sehr dankbar!

Viele Grüße,
Ulla.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Was ist wenn du den String UTF-8 kodierst? PostgreSQL wirft AFAIR UNICODE und UTF8 etwas durcheinander.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

ullat hat geschrieben:wie kann man Sonderzeichen, wie z.B. Umlaute per Python und PyGreSQL in die PostgreSQL Datenbank bekommen?
Hallo Ulla!

Willkommen im Python-Forum!

Ich kenne PyGreSQL nur vom Hören und Sagen. Ich setze *psycopg2* ein. Ich kann mir aber denken, dass PyGreSQL das mit den Umlauten ähnlich wie *psycopg2* macht.

Du darfst die Felder mit den Umlauten nicht direkt in die SQL-Anweisung schreiben. Lass die Datenbankschnittstelle die Arbeit machen. Kümmere dich einfach darum, dass die Daten in Unicode vorliegen.

Code: Alles auswählen

# -*- coding: iso-8859-15 -*-

namen = (
  [u"Ülrich"], 
  [u"Österreicher"]
)
sql = "INSERT INTO tabellenname (name) VALUES (?)"
for name in namen:
    connection.execute(sql, name)
connection.commit()
Vielleicht musst du bei PyGreSQL statt dem "?" einen anderen Platzhalter verwenden.

Umgelegt auf dein Beispiel:

Code: Alles auswählen

sql = "SELECT * FROM A1339 WHERE NAME = ?"
cursor.execute(sql, u"Österreich")
...
mfg
Gerold
:-)

PS: ...und wenn du statt "conn.query" nicht "conn.execute" einsetzen kannst, dann würde ich so schnell wie möglich auf *psycopg2* umsteigen. Je früher, desto besser.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
ullat
User
Beiträge: 3
Registriert: Mittwoch 18. Juli 2007, 14:14

Hallo zusammen,

die Tipps haben mir sehr gehofen. :)

Ebenfalls sehr hilfreich war der folgende Beitrag zu String, Unicode und UTF-8, den ich jedem der ein Umlaut-Problem hat nur weiterempfehlen kann:

http://www.python-forum.de/topic-5095.html

Bevor ich ein SQL-Statement an PyGreSQL übergebe mache ich jetzt folgende Umwandlungsschritte:

Code: Alles auswählen

        statement = statement.decode("latin-1")
        statement = statement.encode("utf-8")
Vielleicht geht es auch in einem Schritt. Aber auf jeden Fall funktioniert es in diesen beiden ....

Vielen Dank!
Ulla.
Byte
User
Beiträge: 63
Registriert: Dienstag 26. September 2006, 07:04

Hi Gerold,

habe das gleiche Problem mit psycopg2, habe aber bisher auch immer die Werte mit den Stringfunktionen von Pyhton eingefügt. Ist das mit dem "?" irgenwo dokumentiert? Funktioniert das auch mit mehreren Werten.

:? Gruß Christian
BlackJack

Das mit dem '?' ist SQL-Standard und auch in PEP 249 - Python Database API Specification v2.0 beschrieben. Die DB API 2.0 wird von allen ernstzunehmenden Datenbankmodulen implementiert.
Byte
User
Beiträge: 63
Registriert: Dienstag 26. September 2006, 07:04

Hallo,

irgendwie bin ich nicht fähig, das hinzukriegen. Es folgt mein Testcode.

Code: Alles auswählen

[quote]connection = pg.connect(dsn)
cursor = connection.cursor()
sql = "SELECT * FROM name WHERE name = ?"
cursor.execute(sql, u"Name")
connection.commit()
In der Logdatei von Postgre sehe ich folgende Fehlermeldung, irgendwie geht das mit dem "?" als Platzhalter nicht, er wird nicht ersetzt.
2007-10-21 17:17:30 STATEMENT: SELECT * FROM name WHERE name = ?
2007-10-21 17:19:01 ERROR: syntax error at end of input at character 34
Habe auch schon probiert, das Leerzeichen vor dem ? und dem = zu entfernen, aber dann meckert er weil er das als Operator ansieht.
2007-10-21 17:15:31 ERROR: operator does not exist: character varying =? at character 30
2007-10-21 17:15:31 HINT: No operator matches the given name and argument type(s). You may need to add explicit type casts.
2007-10-21 17:15:31 STATEMENT: SELECT * FROM name WHERE name=?
Woran könnte das liegen? Irgendwie habe ich da eine Blockade.

Gruß Christian
BlackJack

Hm, da hätte eigentlich `cursor.execute()` schon meckern müssen. Das zweite Argument sollte eine Sequenz mit Argumenten sein und keine Unicode-Zeichenkette.
Byte
User
Beiträge: 63
Registriert: Dienstag 26. September 2006, 07:04

Ich habe eigentlich nur den Code aus Gerolds Posting genommen, weil es bei meiner Anwendung nicht funktioniert hat. Aber auch das geht nicht.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hallo Byte!

Zeige uns doch bitte mal, ein bei dir nicht funktionierendes Codebeispiel. Aber bitte komplett. Nicht nur einen Auschnitt davon.

Dann brauchen wir noch das komplette Traceback. Also die komplette Fehlermeldung die Python ausspuckt.

Dann können wir dir wahrscheinlich sofort sagen, woran es liegt.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Byte
User
Beiträge: 63
Registriert: Dienstag 26. September 2006, 07:04

Hallo,

Mein Code:

Code: Alles auswählen

#!/bin/env python
# -*- coding: iso-8859-15 -*-

import psycopg2 as pg

wert = u"Zeile1"

connection = pg.connect("host=localhost dbname=test user=test password=test")
cursor = connection.cursor()
sql = "SELECT * FROM t_tabelle WHERE spalte1 = ?"
cursor.execute(sql, wert)
connection.commit()
print cursor.fetchall()
Erzeugt folgendes:
Traceback (most recent call last):
File "D:\Programmierung\Faktura\Programm\test.py", line 11, in
cursor.execute(sql, wert)
psycopg2.ProgrammingError: syntax error at end of input
LINE 1: SELECT * FROM t_tabelle WHERE spalte1 = ?
^
Script terminated.

Zeile 10 und 11 ersetzt mit:

Code: Alles auswählen

sql = "SELECT * FROM t_tabelle WHERE spalte1 = 'Zeile1'"
cursor.execute(sql)
ergibt:
[('Zeile1',)]
Script terminated.

Danke für die Hilfe und Gruß

:?: Christian
BlackJack

Wie gesagt, das zweite Argument von `execute()` muss eine Sequenz, also zum Beispiel ein Tupel von Werten sein und nicht ein einzelner Wert.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Mein Fehler!

Du musst bei psycopg2 als Platzhalter verwenden.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hallo!

Ich habe alles mal in ein kleines Beispiel zusammengefasst. Vielleicht kann einer von euch damit etwas anfangen:

http://www.python-forum.de/topic-12304.html

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Byte
User
Beiträge: 63
Registriert: Dienstag 26. September 2006, 07:04

Hallo,

danke Black Jack und Gerold für eure Hilfe. Ich habe mal mein kleines Beispiel mit einem Insert so umgebaut dass es bei mir funktioniert.

Code: Alles auswählen

#!/bin/env python
# -*- coding: iso-8859-15 -*-

import psycopg2 as pg

wert = (u"ÄÖÜß", u"Wert 2")

# Zum einfügen eines einzelnen Wert muss es auch ein Tupel sein
# wert = (u"Wert 1",)

connection = pg.connect("host=localhost dbname=test user=test password=test")
cursor = connection.cursor()
sql = "INSERT INTO t_tabelle values (%s, %s)"
cursor.execute(sql, wert)
connection.commit()

:D Christian
Antworten