Encoding-Problem

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
BlackJack

Hast Du nur die Kommentarzeile geändert? Passt der Kommentar auch zur tatsächlich verwendeten Kodierung in der Quelltextdatei? Was Du bisher über das Testprogramm verraten hast, spricht eher dafür, das die Quelltextdatei UTF-8 kodiert ist.

Welche Kodierung wird in der CSV-Datei verwendet? Und welche Kodierung erwartet die Datenbank?

Fragen über Fragen und ich habe den Eindruck du probierst nur herum und hast den Zusammenhang zwischen Bytes, Kodierungen und Zeichen noch nicht ganz verstanden.
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

Hab das Zeugs alles gelesen.

Die Kommentarzeile hab ich nun geändert, weil ich im MyEclipse gesucht habe, welches Encoding verwendet wird. Hab bisschen gesucht und an 2 STellen stand cp1252. Da ist damit meine Py-Files erstelle, nehm ich an, dass das dann auch das richtige Encoding für die Kommetarzeile ist.
Seit dem komtm für den Test-String, der direkt im Code steht, auch keine Fehlermeldung mehr für das ß.

Das Coding für die Datenbank hat mein DBA mir gesagt, war sehr kryptisch und der Leonidas hat mir das freundlicher Weise in cp1252 übersetzt :)

Das Coding der csv ... nun ... k.A. wie ich das rausbekomme. Excel sagt mir ist ANSI und eine liebe weiterer Quelle meinte auch, ist iso-8859-irgendwas.

Anhand weiterer lieber Tipps hier und dem lesen des Wikis, bin ich dann darauf gekommen, wie ich das jetzt mache.

Nur komm ich absolut nicht weiter :(

Wenn ich IRGENDWAS utf-8 setze wird alles nur noch kryptischer, ich wüsste nicht, wo irgendwas utf-8 kodiert her kommen soll.

Verwende nun daher auch wieder cp1252 für die Py-Datei, lese die csv als iso ein, decode das in unicode, wandel das in cp1252 um und schreibe in die DB .. und hab nun pro Umlaut ein "Sonderzeichen".

Irgendwo stimmt da nun was noch nicht, ich weiß nur nicht an welcher Stelle. Ich sitze da jetzt seit Donnerstag dran und komm kaum weiter, nur dass ich inzwischen ein bisschen mehr Plan von dem Coding Zeugs habe, wenn auch noch nicht vollständig durchgestiegen bin.
Zuletzt geändert von meneliel am Dienstag 30. September 2008, 13:03, insgesamt 1-mal geändert.
BlackJack

Also lass uns doch einfach nochmal von vorne Anfangen, bzw. von Hinten. Der Weg ist ja `CSV-Datei → Programm → Datenbank` und bei jedem '→' müsste umkodiert werden, bzw. beim ersten Pfeil in Unicode und beim zweiten dann wieder in Bytes.

Nimm mal ``test = u'\xe4'``, das ist völlig sicher ein 'ä' als Unicode-Objekt und versuche das so in die Datenbank zu bekommen, dass es in ArcGIS auch als 'ä' erscheint. Oder alternativ frage mal ein Datum mit einem 'ä' aus der Datenbank ab und schau nach wie das kodiert ist, also welchen Bytewert die DB dafür liefert.

Als zweiten Schritt suchst Du Dir in der CSV-Datei ein 'ä' und schaust mal, wie die Zeichenkette, also eigentlich Bytefolge als `repr()` aussieht. Am besten mal zeigen, dann wissen wir welchen Bytewert oder vielleicht auch welche Byte*werte* in der CSV-Datei stehen.
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

Hallo BlackJack,

Ich habe mal angefangen und versucht das ``test = u'\xe4'`` in die Datenbank zu schreiben. Nur vorsichtshalber mal der Code dazu und auch noch der meiner KLasse, die das Schreiben in die DB übernimmt, wer weiß, vielleicht liegt ja auch dort das Problem:

Code: Alles auswählen

# -*- coding: cp1252 -*- 
db = DB()
test = u'\xe4'
x = test.encode("cp1252")
insert_string = "INSERT INTO ADRESSEN (PfBezNr) VALUES('%s')" %x
db.selection(insert_string)


# class DB:
    '''Klasse die Verbindungsaufbau und Kommunikation mit der Datenbank übernimmt'''
    def __init__(self):
        my_dsn = cx_Oracle.makedsn("host",1234,"sid")
        self.db = cx_Oracle.connect("user","pwd",my_dsn)
        print self.db
                
    def __del__(self):
        self.db.close()
    
    def selection(self,query):
        cursor = self.db.cursor()
        cursor.execute(query)
        try:
            sel = cursor.fetchall()
            cursor.close
            return sel
        except:
            cursor.close
            self.db.commit()
(die Einrückung kommt jetzt durchs Copy/Paste)

Ergebnis:
als encode - Parameter hab ich jetzt noch mal alles durchprobiert. Weder cp1252, iso und auch utf-8 bringt alles umgedrehte Fragezeichen.´, utf-8 zwei, die anderen je eins. Also hab ich es einfach noch mal probiert OHNE mir über codings Gedanken zumachen und einfach '\xe4' reingeschrieben --> gleiches Ergebnis: ein umgedrehtes Fragezeichen, sowohl im ArcGIS, als auch im SQL-Developer


Test 2:
aus einer in der gleichen Datenbank liegenden anderen Tabelle, wo es Zeilen mit Umlauten gibt, diese über select ausgelesen und mir ohne irgendwas zu machen die ganze Zeile ausgeben lassen mittels:

Code: Alles auswählen

print repr(row)
Ergebnis: statt ä ein a, ö ein o und u ein ü und ß ein ? in der Console von MyEclipse.
-------------

die csv-Datei nehm ich mir dann nach der MIttagspause mal vor, aber mir scheint, das Problem liegt dann eher auf Datenbankseite? Zumindest einen einfachen Test-String müsste ich doch irgendwie korrekt in die DB bekommen. :(

----
BlackJack

Das Ergebnis von Test 2 mag ich nicht glauben, denn `repr()` sollte reine ASCII-Zeichen erzeugen und alles ausserhalb von ASCII als '\x??' Sequenz darstellen, wobei die ? für Hexadezimalziffer stehen.
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

.. das hätte ich eben auch erwartet ...

... hab gerade auch getestet, ein einfaches Script wo nur print repr('ö') drin steht, liefert erwartetes Ergebnis: '\xf6'

ich räum mal den code auf und teste noch mal ...

Dennoch wundert es mich, dass ich den einfachen Test-String bisher nicht "korrekt" in die DB bekommen hab :(
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Übergabe der Daten wie so oft falsch, siehe: [wiki]Parametrisierte SQL-Queries[/wiki]

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Code: Alles auswählen

# -*- coding: cp1252 -*-
db = DB()
test = u'\xe4'
x = test.encode("cp1252")
insert_string = "INSERT INTO ADRESSEN (PfBezNr) VALUES('%s')" %x
db.selection(insert_string)
Was passiert denn hier eigentlich beim Erstellen des insert_string? Wird da nicht der Unicode-String test wieder in einen Byte-String mit der cp1252 Codierung gewandelt? Ist also das explizite Encodieren in Zeile 4 nicht überflüssig? Irgend wie hab ich das Gefühl ich hab das auch alles noch nicht zu 100% begriffen ... :-(
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Das meinte ich ja mit [wiki]Parametrisierte SQL-Queries[/wiki];)

Ich würde es vielleicht so machen:

Code: Alles auswählen

class DB:
    ...
    def execute(self, query, data):
        cursor = self.db.cursor()
        cursor.execute(query, data)

db = DB()
db.execute(
    query = "INSERT INTO ADRESSEN (PfBezNr) VALUES('%s')",
    data = (u'\xe4',)
)
EDIT: @meneliel: Bei cursor.close fehlen die Klammern ;) Ohne die wird nix gemacht...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

@ jens: das funktioniert aber nicht

Hab jetzt mal einfach mit ipython probiert:

Code: Alles auswählen

In [29]: select = "INSERT INTO ADRESSEN (PfBezNr) VALUES('%s')"
In [32]: test = 'ö'
In [35]: cursor = db.cursor()
In [36]: cursor.execute(select, test)
---------------------------------------------------------------------------
DatabaseError                             Traceback (most recent call last)

C:\...\Desktop\<ipython console>

DatabaseError: ORA-01036: illegal variable name/number

In [38]: cursor.execute("INSERT INTO ADRESSEN (PfBezNr) VALUES('%s')",test)
---------------------------------------------------------------------------
DatabaseError                             Traceback (most recent call last)
C:\...\Desktop\<ipython console>
DatabaseError: ORA-01036: illegal variable name/number

In [37]: cursor.execute(select %test )
# Eintrag aber wieder mit Sonderzeichen in der Datenbank
Hab dann auch das Script aufgeräumt um aus einer anderen Tabelle ein Umlaut auszulesen (das was BlackJack nicht glauben wollte):

Code: Alles auswählen

In [18]: select = '''SELECT OBJECTID, Strasse FROM GC_TEST_GK WHERE OBJECTID = 3'''
In [21]: cursor = db.cursor()
In [23]: cursor.execute(select)
Out[23]: [<cx_Oracle.NUMBER with value None>, <cx_Oracle.STRING with value None>]
In [24]: sel = cursor.fetchall()
In [26]: sel
Out[26]: [(3, 'Am Kappele')]

# müsste eigentlich heißten "Am Käppele"
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

jens hat geschrieben: EDIT: @meneliel: Bei cursor.close fehlen die Klammern ;) Ohne die wird nix gemacht...
^^ das war mir direkt nach dem Posten hier auch schon aufgefallen und hab es dannb gleich behoben ^^
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Vermutlich ist %s der falsche Platzhalter.

Aus http://www.python.org/dev/peps/pep-0249/ :
paramstyle

String constant stating the type of parameter marker
formatting expected by the interface. Possible values are
[2]:

'qmark' Question mark style,
e.g. '...WHERE name=?'
'numeric' Numeric, positional style,
e.g. '...WHERE name=:1'
'named' Named style,
e.g. '...WHERE name=:name'
'format' ANSI C printf format codes,
e.g. '...WHERE name=%s'
'pyformat' Python extended format codes,
e.g. '...WHERE name=%(name)s'
Mach mal ein print db.paramstyle

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

Code: Alles auswählen

In [41]: print db.paramstyle
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

C:\Dokumente und Einstellungen\mengel\Desktop\<ipython console>

AttributeError: 'cx_Oracle.Connection' object has no attribute 'paramstyle'
? funktioniert übrigens auch nicht.

Die Frage ist: löst das denn mein Encoding Problem? Bisher konnte ich so jedefalls immer aus der DB lesen und in sie schreiben. Nur dass ich seit letzte WOche plötzlich Probleme mit den Umlauten habe.

Und wenn ich aus der DB lese, oder Werte ohne Variablen rein schreibe (z.B. INSERT INTO ADRESSEN (PfBezNr) VALUES('ö')) - seh ich immer noch keine Umlaute ....
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

google gefragt und das gefunden:

Code: Alles auswählen

 >>> import cx_Oracle
 >>> cx_Oracle.paramstyle
'named'
Also muß es so gehen:

Code: Alles auswählen

db = DB()
cursor = self.db.cursor()
cursor.execute(
    "INSERT INTO ADRESSEN (PfBezNr) VALUES(:data)",
    { "data": u'\xe4' }
)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

danke ...
... würde aber das Umschreiben von ca. 15 funktionierenden Scripten mit sich ziehen ... ist dann vielleicht sicher angebracht, aber löst aktuell das Problem nicht, welches ich dringend noch diese Woche lösen will/muss um nächste Woche mit beruhigt in meine Flitterwochen zu fahren ...^^

Davon abgesehen, dass ich kein Unicode an der Stelle verwenden kann führt ein

Code: Alles auswählen

cursor.execute("INSERT INTO ADRESSEN (PfBEZNR) VALUES(:data)", {"data":u'\xe4'.encode("cp1252")})
nicht zur Lösung und ich habe weiterhin Umlaute in der Datenbank.

PS: nach dem Execute hab ich natürlich auch ein commit gemacht (nur um der Frage vorzubeugen ...^^)
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dann ist wohl einfach "cp1252" falsch. Bei MySQL kann man auch explizit sagen, welches Encoding verwendet wird.

Schau dich mal hier um: http://www.google.de/search?hl=de&q=cx_ ... uche&meta=

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@meneliel: Kann es sein, dass die DB gar kein `str` liefert, sondern `cx_Oracle.STRING` und das die als `str()`/`repr()`-Darstellung aus einem 'ä' ein 'a' machen?

Hast Du der Vorschlag mit den Platzhaltern im SQL und direktes verfüttern von Unicode-Objekten an `execute()` eigentlich schon ausprobiert? Wenn Du Glück hast, kümmert sich das DB-Modul dann automatisch um die korrekte Kodierung.
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

aber mein sqldeveloper sagt mir das das environment encoding cp1252 ist, mein DBA teilte mir gleiches mit, auf die Frage, wie das DB-Encoding ist.
Und ich hab ja jetzt auch schon probiert utf-8 oder iso-codierte Strings darein zuschreiben.

*aufgeb*
meneliel
User
Beiträge: 256
Registriert: Montag 25. Juni 2007, 08:35
Kontaktdaten:

BlackJack hat geschrieben:@meneliel: Kann es sein, dass die DB gar kein `str` liefert, sondern `cx_Oracle.STRING` und das die als `str()`/`repr()`-Darstellung aus einem 'ä' ein 'a' machen?
:( k.A.
BlackJack hat geschrieben: Hast Du der Vorschlag mit den Platzhaltern im SQL und direktes verfüttern von Unicode-Objekten an `execute()` eigentlich schon ausprobiert? Wenn Du Glück hast, kümmert sich das DB-Modul dann automatisch um die korrekte Kodierung.
ja hab ich und ja auch schon geschrieben, dass das mit Unicode nicht geht.

Code: Alles auswählen

In [49]: cursor.execute("INSERT INTO ADDRESSEN (PfBEZNR) VALUES(:data)", {"data":u'\xe4'})
---------------------------------------------------------------------------
NotSupportedError                         Traceback (most recent call last)

C:\Dokumente und Einstellungen\mengel\Desktop\<ipython console>

NotSupportedError: Variable_TypeByValue(): unhandled data type unicode
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

btw. bei MySQL kann man beim erstellen einer Datenbank auch ein encoding angeben. Ist das evtl. auch bei Oracle möglich?

Hast du dir aus meiner google suche die Seite http://osdir.com/ml/python.db.cx-oracle ... 00007.html angesehen? Da ist was mit select value from v$nls_parameters where parameter = 'NLS_CHARACTERSET'

Mit was siehst du denn, ob die Daten richtig sind oder nicht? Vielleicht zweigt dein Datenbank-anguck-programm die Daten einfach nur falsch an.
Vergleich das doch mal direkt in Python, ungefähr so:
TEST_STRING = u'\xe4'
insert mit TEST_STRING.encode("cp1252")
select des wertes, dann ein print select_result.decode("cp1252") == TEST_STRING

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten