Das deutsche Python-Forum

10 Jahre Diskussionen rund um die Programmiersprache Python
Aktuelle Zeit: Mittwoch 22. Oktober 2014, 09:55

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 43 Beiträge ]  Gehe zu Seite 1, 2, 3  Nächste
Autor Nachricht
 Betreff des Beitrags: Encoding-Problem
BeitragVerfasst: Freitag 26. September 2008, 10:01 
User

Registriert: Montag 25. Juni 2007, 09:35
Beiträge: 256
Hallo,

ich hab jetzt schon ne ganze Weile hier gesucht und auch jede Menge zu dem Thema gefunden udn viel rumprobiert, aber irgendwie komme ich nicht weiter.

Ich lese aus einem *.csv-File Adressen aus und will die in eine Oracle Datenbank schreiben.
Dort Sachen rein zu schreiben, hatte ich bisher noch nie Probleme mit Umlauten.

Allerdings habe ich jetzt halt diese CSV von einem Kunden und ich krieg die eingelesenen Zeilen nicht mal in der Console von MyEclipse oder in der Windowskonsole richtig ausgegeben, hab ständig Umlaut-Fehler, so wird z.B ein ä immer als \xe4 ausgegeben, in der Windowskonsole als o mit so nem komischen Zeichen drüber.

Hab dann probiert:
  1. coding = "iso-8859-1"
  2. insert_list.append(row[fields["Strasse"]].encode(coding)+ " " + str(i))
  3. # row[fields["Strasse"]] liefert mir als String den Straßennamen
  4.  
Highlighting by GeSHi


Aber macht keinen Unterschied, das gleich Problem. Wenn ich dass dann aber in der WIndows Konsole und nicht im MyEclipse Starte kommt folgende Fehlermeldung:

  1. Traceback (most recent call last):
  2.   File "x:\xxx\ccc\eee\src\create_adresses.py", line 108, in
  3. <module>
  4.     main(infile)
  5.   File "x:\xxx\ccc\eee\src\create_adresses.py", line 99, in main
  6.     readcsv(infile,db)
  7.   File "x:\xxx\ccc\eee\src\create_adresses.py", line 71, in readcsv
  8.     values = build_insert_list(row,i)
  9.   File "x:\xxx\ccc\eee\src\create_adresses.py", line 38, in build_insert_list
  10.     insert_list.append(row[fields["Kirchenbezirk"]].encode(coding))
  11. UnicodeDecodeError: 'ascii' codec can't decode byte 0xfc in position 1: ordinal not in range(128)
  12.  
Highlighting by GeSHi


Was ist das für ein Fehler? Und warum wird der in MyEclipse NICHT geworfen?
Und wie bekomme ich nun meine Adressen richtig codiert. Ich nehme an, wenn ich in der Console richtige Umlaute sehe, werden sie dann auch so in die Datenbank geschrieben.

Ein Kollege hat auch irgendwo ein kleines Modul gefunden:
  1. import csv, codecs, cStringIO
  2.  
  3. class UTF8Recoder:
  4.     """
  5.    Iterator that reads an encoded stream and reencodes the input to UTF-8
  6.    """
  7.     def __init__(self, f, encoding):
  8.         self.reader = codecs.getreader(encoding)(f)
  9.  
  10.     def __iter__(self):
  11.         return self
  12.  
  13.     def next(self):
  14.         return self.reader.next().encode("utf-8")
  15.  
  16. class UnicodeReader:
  17.     """
  18.    A CSV reader which will iterate over lines in the CSV file "f",
  19.    which is encoded in the given encoding.
  20.    """
  21.  
  22.     def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
  23.         f = UTF8Recoder(f, encoding)
  24.         self.reader = csv.reader(f, dialect=dialect, **kwds)
  25.  
  26.     def next(self):
  27.         row = self.reader.next()
  28.         return [unicode(s, "utf-8") for s in row]
  29.  
  30.     def __iter__(self):
  31.         return self
  32.  
  33. class UnicodeWriter:
  34.     """
  35.    A CSV writer which will write rows to CSV file "f",
  36.    which is encoded in the given encoding.
  37.    """
  38.  
  39.     def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
  40.         # Redirect output to a queue
  41.         self.queue = cStringIO.StringIO()
  42.         self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
  43.         self.stream = f
  44.         self.encoder = codecs.getincrementalencoder(encoding)()
  45.  
  46.     def writerow(self, row):
  47.         self.writer.writerow([s.encode("utf-8") for s in row])
  48.         # Fetch UTF-8 output from the queue ...
  49.         data = self.queue.getvalue()
  50.         data = data.decode("utf-8")
  51.         # ... and reencode it into the target encoding
  52.         data = self.encoder.encode(data)
  53.         # write to the target stream
  54.         self.stream.write(data)
  55.         # empty queue
  56.         self.queue.truncate(0)
  57.  
  58.     def writerows(self, rows):
  59.         for row in rows:
  60.             self.writerow(row)
  61.  
Highlighting by GeSHi


Das haben wir dann benutzt und das ganze folgender Maßen eingebunden:
  1. csv_file = coding.UnicodeReader(open(infile), delimiter=';', encoding="iso-8859-15")
  2.  
Highlighting by GeSHi


Aber da bekam ich Fehler von der Datenbank, dass das keine Strings seien.

Wäre für Hinweise sehr Dankbar, denn komme im Moment nicht so richtig weiter.

Grüße.


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Freitag 26. September 2008, 10:30 
Administrator
Benutzeravatar

Registriert: Freitag 20. Juni 2003, 17:30
Beiträge: 15952
Vorweg zwei Fragen: welches Encoding will die Datenbank haben? Welches Encoding ist in der CSV-Datei benutzt?

_________________
My god, it's full of CARs! | Leonidasvoice vs Modvoice


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Freitag 26. September 2008, 10:36 
User

Registriert: Montag 25. Juni 2007, 09:35
Beiträge: 256
welches die CSV Datei hat, weiß ich nicht und leider auch nicht, wie ich das rausbekomme. Ich habe die so vom Kunden bekommen.
Die Datenbank:WE8MSWIN1252 was auch immer das ist. Zumindest war das die Antwort unserers DBAs auf meine Anfrage dazu gestern.

Aber schon bevor die Daten in die Datenbank kommen, hatte ich mir nun zu Testzwecken einfach die "INSERT"-Statements ausgeben lassen und dort treten halt schon die Encoding-Fehler auf.
Allerdings erst dort. Ich übergebe die Werte ja aus einem Tupel, die in die DB eingefügt werden sollen und wenn ich mir die Liste, aus dem ich das Tupel mache ausgeben lassen, sind alle Umlaute korrekt.


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Freitag 26. September 2008, 11:02 
Administrator
Benutzeravatar

Registriert: Freitag 20. Juni 2003, 17:30
Beiträge: 15952
meneliel hat geschrieben:
welches die CSV Datei hat, weiß ich nicht und leider auch nicht, wie ich das rausbekomme.

Du öffnest sie in einem Editor als Latin-9 (ISO-8859-15) und guckst ob "Sonderzeichen" passen, wenn nicht dann als UTF-8 usw. Bis dann irgendwann alles passt.

meneliel hat geschrieben:
Die Datenbank:WE8MSWIN1252 was auch immer das ist.

Also musst du in deinem Python-Programm höchstwarscheinlich CP-1252 als Ausgabeencoding nutzen.

meneliel hat geschrieben:
Aber schon bevor die Daten in die Datenbank kommen, hatte ich mir nun zu Testzwecken einfach die "INSERT"-Statements ausgeben lassen und dort treten halt schon die Encoding-Fehler auf.

Das muss nicht sein: \xe4 ist kein Escape-Fehler sondern ein Zeichen, dessen ASCII-Wert über 128 ist, und wird daher vom Python-Interpreter escaped. In der Windowskonsole können auch richtige Zeichen falsch dargestellt werden, wenn das Encoding der AUsgabe nicht mit dem Encoding welches die Konsole erwartet, übereinstimmt.

Die Verarbeitung sieht so aus:
Eingabe -> CSV -> in Unicode mit Codec X wandeln -> Verarbeitung -> In CP-1252 enkodierte Bytestrings konvertieren -> an die Datenbank weitergeben.

_________________
My god, it's full of CARs! | Leonidasvoice vs Modvoice


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Freitag 26. September 2008, 11:35 
User

Registriert: Montag 25. Juni 2007, 09:35
Beiträge: 256
Danke für die Hniweise.

Die Sache ist: im Normalen Text-Editor öffne, seh ich alle Umlaute richtig. geh ich auf Speichern unter, ist vorausgewählt ANSI, müsste dann ja iso-8859-15 sein, oder? Bei der Datei sieht auch alles richtig aus, wenn ich sie im Ultra-Edit öffne.

Ich weiß nicht, und hab nix gefunden, wie ich eine Dtei gezielt mit einem Coding öffnen kann :(

Hab dann zum Testen folgendes probiert: hab die Datei einfach mal im Editor als UTF-8 gespeichert und dann in der Zeile:
  1. csv_file = coding.UnicodeReader(open(infile), delimiter=';', encoding="utf-8")
Highlighting by GeSHi


angegeben.

Das cp-1252 müsste dann hier angegeben werden?
  1. coding = "CP-1252"
  2. insert_list.append(row[fields["Strasse"]].encode(coding)+ " " + str(i))
  3.  
Highlighting by GeSHi


Nur bekomm ich da zurück, dass dies ein unbekanntes Coding ist: LookupError: unknown encoding: cp-1252
Sowohl wenn ich cp klein, als auch wenn ich es groß schreibe.

Hab dann probiert, das ganze als utf-8 in die Datenbank zu schreiben: da bekomm ich noch mehr "komische" Sonderzeichen. Wenn ich zum Schluss probiere die Unicode-utf-8 Strings in iso-8859-15 in die DB zu schreiben bekomme ich die Meldung:
UnicodeEncodeError: 'charmap' codec can't encode character u'\ufeff' in position 0: character maps to <undefined>

Ist die Wahl des oben geposteten UnicodeReaders und der entsprechende Aufruf überhaupt der richtige Weg?[/code]


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Freitag 26. September 2008, 12:03 
Administrator
Benutzeravatar

Registriert: Freitag 20. Juni 2003, 17:30
Beiträge: 15952
meneliel hat geschrieben:
Die Sache ist: im Normalen Text-Editor öffne, seh ich alle Umlaute richtig. geh ich auf Speichern unter, ist vorausgewählt ANSI, müsste dann ja iso-8859-15 sein, oder?

Nein, denn sowas wie ANSI gibt es an sich gar nicht. Das wird wohl irgendein ISO 8859-Codec sein, aber welcher ist unbekannt.

meneliel hat geschrieben:
Bei der Datei sieht auch alles richtig aus, wenn ich sie im Ultra-Edit öffne.

Mit welchem Encoding?

meneliel hat geschrieben:
Ich weiß nicht, und hab nix gefunden, wie ich eine Dtei gezielt mit einem Coding öffnen kann :(

In Python oder im Editor? Wenn letzteres, dann solltest du dir einen besseren Editor besorgen, in sinnvollen Programmen kann man das Encoding zur Laufzeit ändern und gucken was passiert.

meneliel hat geschrieben:
Hab dann probiert, das ganze als utf-8 in die Datenbank zu schreiben: da bekomm ich noch mehr "komische" Sonderzeichen.

Natürlich, was du machst ist ja auch Programming by Accident. Wenn du das verstehen willst, lies dir die Unicode-Seiten im Wiki durch und meine Folien vom 14. Usertreffen. Wenn es dir egal ist, dann befolge die Reihenfolge, die ich dir gepostet habe.

meneliel hat geschrieben:
Ist die Wahl des oben geposteten UnicodeReaders und der entsprechende Aufruf überhaupt der richtige Weg?

Also ich würde ihn weglassen, das ist noch ein Stück Code dass zu unflexibel ist un nochmal extra angepasst werden müsste.

_________________
My god, it's full of CARs! | Leonidasvoice vs Modvoice


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Freitag 26. September 2008, 12:04 
Moderator
Benutzeravatar

Registriert: Freitag 4. August 2006, 15:56
Beiträge: 6794
Wohnort: Hamburg
meneliel hat geschrieben:
Nur bekomm ich da zurück, dass dies ein unbekanntes Coding ist: LookupError: unknown encoding: cp-1252
Sowohl wenn ich cp klein, als auch wenn ich es groß schreibe.

Probiere mal "cp1252" ohne das "-" ;-)


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Freitag 26. September 2008, 12:21 
User

Registriert: Montag 25. Juni 2007, 09:35
Beiträge: 256
Hyperion hat geschrieben:
meneliel hat geschrieben:
Nur bekomm ich da zurück, dass dies ein unbekanntes Coding ist: LookupError: unknown encoding: cp-1252
Sowohl wenn ich cp klein, als auch wenn ich es groß schreibe.

Probiere mal "cp1252" ohne das "-" ;-)


^^ ahhh ;-)

Führt aber bei oben genannten Vorgehen auch nicht zur Lösung und bringt keine Änderung. Dann such ich erst mal nach ner Alternative zu dem Unicode-Reader, um die aus der csv-ausgelesenen Zeile in Unicode umzuwandeln.

Im Ultra-Edit sieht es mit ISO 8859-xx richtig aus.

Zitat:
In Python oder im Editor?

hmm ... Beides? Meinte eigentlich im Editor. Dachte in Python geb ich das am Beginn des Moduls ein mit:
# -*- coding: iso-8859-1-*-

[/quote]


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Freitag 26. September 2008, 12:27 
Administrator
Benutzeravatar

Registriert: Freitag 20. Juni 2003, 17:30
Beiträge: 15952
meneliel hat geschrieben:
hmm ... Beides? Meinte eigentlich im Editor. Dachte in Python geb ich das am Beginn des Moduls ein mit:
# -*- coding: iso-8859-1-*-

Das bezeichnet nur das Encoding welches verwendet wird um u""-Strings in Unicode zu dekodieren.

_________________
My god, it's full of CARs! | Leonidasvoice vs Modvoice


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Freitag 26. September 2008, 15:01 
User

Registriert: Montag 25. Juni 2007, 09:35
Beiträge: 256
*langsam am Verzweifeln bin*

Also was ich aus der csv ausgelesen hab decode ich in unicode und mache hinterher wieder Byte-Strings daraus.

Hab mir jetzt die Seiten im Wiki durchgeguckt und dann auch noch die Folien vom Usertreffen und denke ich hab das soweit auch verstanden und scheint ja nun auch alles ganz logisch.

Dann müsste aber DAS funktionieren:

  1. coding_csv = "iso-8859-1"
  2. # hab hier alternativ auch -15 probiert
  3. coding_db = "cp1252"
  4. insert_list.append(row[fields["PLZ"]].decode(coding_csv).encode(coding_db))
  5.  
Highlighting by GeSHi


Keine Veränderung in der Datenbank - dort sehe ich statt einem ö z.B. immer noch ein umgedrehtes Fragezeichen.

:(


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Freitag 26. September 2008, 15:45 
Moderator
Benutzeravatar

Registriert: Freitag 4. August 2006, 15:56
Beiträge: 6794
Wohnort: Hamburg
  1. row[fields["PLZ"]]
  2.  
Highlighting by GeSHi

Sicher, dass das auch ein Bytestring ist? Und vor allem, wieso wandeslt Du den nicht schon vorher in Unicode?

Hast Du mal einen Test durchgeführt und einen cp1252 kodierten Bytestring in die DB geschrieben? Evtl. stimmt das Encoding ja gar nicht?

Was genau bedeutet denn "dort sehe ich ..."? Was ist dort? Liest Du es wieder aus? Nutzt Du einen externen Viewer? (Wenn ja, kann der die Zeichen überhaupt richtig darstellen?)


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Freitag 26. September 2008, 16:11 
User

Registriert: Montag 25. Juni 2007, 09:35
Beiträge: 256
Hyperion hat geschrieben:
  1. row[fields["PLZ"]]
  2.  
Highlighting by GeSHi

Sicher, dass das auch ein Bytestring ist? Und vor allem, wieso wandeslt Du den nicht schon vorher in Unicode?

Hast Du mal einen Test durchgeführt und einen cp1252 kodierten Bytestring in die DB geschrieben? Evtl. stimmt das Encoding ja gar nicht?

Was genau bedeutet denn "dort sehe ich ..."? Was ist dort? Liest Du es wieder aus? Nutzt Du einen externen Viewer? (Wenn ja, kann der die Zeichen überhaupt richtig darstellen?)


row ist eine Zeile in der csv, die hab ich zu dem zeitpunkt einfach nur geöffnet und gehe dann halt zeile für zeiel durch

fields["PLZ"] : fields ist ein Dictionary in dem ich abgespeichert habe, an welcher Stelle der CSV der entsprechende Wert steht, da ich ca. 20 Felder in der csv habe und nur 15 brauche, fand ich es einfach zu lesen den Index so zuzuordnen, als Zahl, ist im prinzip also nix anderes wie:

  1. csv_file = csv.reader(open(infile), delimiter=';')
  2. for row in csv_file:
  3.     # einiges an code, was mir i ermittelt
  4.     i = xyz
  5.     values = build_insert_list(row,i)
  6.  
  7. def build_insert_list(row,i):
  8.     coding_csv = "iso-8859-1"
  9.     coding_db = "cp1252"
  10.     insert_list = list()
  11.     insert_list.append(row[fields["PLZ"]].decode(coding_csv).encode(coding_db))
  12.     ....
  13.  
Highlighting by GeSHi


Wann kann/sollte ich die Werte aus row denn vorher umwandeln? Hatte es erst mit dem UniCode Reader, aber (vielleicht hab ich das auch net richtig verstanden) Leonidas meinte, den nicht verwenden.

Und was soll es sonst sein, wenn kein Bytestring? Unicode ist es jedenfalls nicht.
Und
  1. print type(row[fields["PLZ"]])
  2. # gibt zurück:
  3. <type 'str'>
  4.  
Highlighting by GeSHi




Zumindest ist die CSV explizit als Windows-Ansi gespeichert wurden.

Ich erzuege doch cp1252 kodierte Bytestrings, die ich in die DB schreibe? Wie soll ich das anders testen?

Hab statt cp1252 auch schon iso-8859-1 und 15 und utf-8 und utf-16 probiert.

".. dort sehen..." heißt SQL_Developer und/oder ArcGIS ArcCatalog. Hab auch schon überlegt, dass es einfach nur falsch angezeigt wird und daher den nächste Verarbeitungsschritt probiert. Dort wurden dann aber die Adressen mit Umlauten nicht erkannt und auch dort mit Sonderzeichen ausgegeben, was am Ende heißt, das 1/3 der Adressen nicht gefunden werden kann, bei einem Testausschnitt der Daten.[/code]


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Freitag 26. September 2008, 17:29 
Moderator
Benutzeravatar

Registriert: Freitag 4. August 2006, 15:56
Beiträge: 6794
Wohnort: Hamburg
Naja, Du könntest ja einfach mal einen Unicode-String nehmen und explizit als cp1252 kodieren und dann in die DB schreiben.
  1. test = u"Hällö Wült!"
  2. # Schreiben in die DB per test.encode("cp1252")
  3.  
Highlighting by GeSHi

So weißt Du ja, dass in test auch wirklich das drinsteht, was Du willst / denkst. Wenn das klappt, so liegt das Problem def. noch bei Verarbeiten der csv-Daten. Wenn nicht, ist eben beim DB-Zugriff noch was im argen.


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Montag 29. September 2008, 08:44 
User

Registriert: Montag 25. Juni 2007, 09:35
Beiträge: 256
*kopf gegen Wand schlag*

Ja klar... bin im Moment bisschen langsam und hatte nicth sofort gecheckt, was du meintest.

Also ein Test-Datensatz zu codieren und in die DB zu schreiben, einfach mit:

  1. test = u"üljkj äöiß"
  2. x = test.encode("cp1252")
  3. insert_string = "INSERT INTO ADRESSEN (Orts) VALUES('%s')" %x
  4.  
  5. UnicodeEncodeError: 'charmap' codec can't encode character u'\x9f' in position 13: character maps to <undefined>
  6.  
Highlighting by GeSHi


Wirft schon beim encoding ein Problem mit dem ß, dass kann irgendwie nicht encodet werden. Ohne ß wird in die Datenbank geschrieben, allerdings mit gleichem Ergebnis wir letzte Woche: nur umgedrehte Fragezeichen sind zu sehen, keine Umlaute.

Wenn ich hingegen den Test-String oder eine ganze Zeile der Daten, die eigentlich in die DB sollen in eine TXT-Datei schreibe, sieht beim öffnen im Editor und Ultra-Edit alles richtig aus. Seltsamer weise wird beim Encoden hier kein Fehler geworfen, wenn ein ß vorkommt, mag aber daran liegen, dass ein eingelesener String ja erst in unicode decodiert wird und dann wieer encodiert?


Nach oben
 Profil  
 
 Betreff des Beitrags:
BeitragVerfasst: Montag 29. September 2008, 09:52 
Moderator

Registriert: Mittwoch 26. Januar 2005, 00:29
Beiträge: 23856
@meneliel: Bei Deinem Test fehlt schon wieder etwas wichtiges: Wie ist die Quelltextdatei kodiert und hast Du das auch als "coding cookie"-Kommentar angegeben?

`test` enthält hier nämlich mit Sicherheit schon "Müll" weil ein echtes 'ß' problemlos als cp1252 kodiert werden kann.

Das die Fehlermeldung von "position 13" spricht, bei einem Unicode-Objekt, das eigentlich nur 10 Zeichen enthält, sollte auch zu denken geben.

Aufgrund der Fehlermeldung tippe ich jetzt mal darauf, dass die Quelltextdatei UTF-8 kodiert ist, aber einen Kodierungskommentar mit latin-1 oder ISO-8859-1 besitzt bzw. das aus irgend einem Grund angenommen wird.


Nach oben
 Profil  
 
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 43 Beiträge ]  Gehe zu Seite 1, 2, 3  Nächste

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.

Suche nach:
Gehe zu:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Deutsche Übersetzung durch phpBB.de