Umlaute in Datei schreiben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Zubi
User
Beiträge: 10
Registriert: Donnerstag 29. November 2018, 13:35

Hallo zusammen,

ich möchte Umlaute in eine csv-Datei schreiben und wieder auslesen. Wenn ich das Programm aus Thonny (Arbeite auf Raspberry pi) starte dann funktioniert alles, wenn ich es jedoch aus dem Terminal starte kommt immer der Fehler: "ascii codec can't encode character u'\xe4' in Position 9: ordinal not in range (128)"

Ich hab jetzt schon viel recherchiert und weiß nun, dass es an der Kodierung liegt. Also habe ich schon mit dem utf-8 Schlüssel und vielen anderen Möglichkeiten herumgespielt aber bekomme es einfach nicht zum laufen.

Kann mir bitte einer ein kurzes Bsp. geben wie ich an die Sache heran gehen muss ich bin hier grad am verzweifeln. :cry:

LG Zubi
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Zubi: öffne die Datei zum Schreiben mit explizitem Encoding.
Was hast Du denn versucht. Zeige Deinen Code inklusive Fehlermeldung.
Zubi
User
Beiträge: 10
Registriert: Donnerstag 29. November 2018, 13:35

Es ist ein recht langes Programm deshalb stelle ich hier mal nur den relevanten Teil ein.

Code: Alles auswählen

#-*- coding: utf-8 -*-
def new():                                          
    def quit():
        eingabeFenster.quit()
        eingabeFenster.destroy()
        
    def check():
       
        with codecs.open("Artikel.csv", "r", "utf-8") as file:      #Datei wird zum lesen geoeffnet
    
            for line in file:                       #Alle Daten in der CSV-Datei durchgehen
                
                data = line.strip().split(";")      #Daten in eine Liste umformen und an ; Trennen
                if entryNumber.get() in data or entryKoordinate.get() in data:       #ist eingegebene Artikelnummer in der Liste "data"
                    
                    vorhanden()                     #fenster mit dem hinweis dass Artikel schon vorhanden
                    eingabeFenster.quit()           #Eingabefenster wird wieder geschlossen
                    eingabeFenster.destroy()        # "
                    break
                                
        with codecs.open("Artikel.csv", "a", "utf-8") as csvfile:
            fieldnames = ["Fachkoordinate", "Artikelnummer"]
            writer = csv.DictWriter(csvfile, fieldnames=fieldnames, delimiter=";") 
            writer.writerow({"Fachkoordinate": entryKoordinate.get(), "Artikelnummer": entryNumber.get()})
            showinfo('Hinweis', 'Artikel wurde angelegt')
Fehlermeldung:

Code: Alles auswählen

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1545, in __call__
    return self.func(*args)
  File "PbL1_0.py", line 87, in check
    writer.writerow({"Fachkoordinate": entryKoordinate.get(), "Artikelnummer": entryNumber.get()})
  File "/usr/lib/python2.7/csv.py", line 152, in writerow
    return self.writer.writerow(self._dict_to_list(rowdict))
  File "/home/pi/rpi_ws281x/python/unicodecsv/py2.py", line 86, in writerow
    _stringify_list(row, self.encoding, self.encoding_errors))
  File "/usr/lib/python2.7/codecs.py", line 706, in write
    return self.writer.write(data)
  File "/usr/lib/python2.7/codecs.py", line 369, in write
    data, consumed = self.encode(object, self.errors)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 3: ordinal not in range(128)
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Das ist ein bekannter Bug vom csv-Modul. Leider existieren dazu nur mehr oder weniger krude Workarounds:

Code: Alles auswählen

csv.DictWriter.writerow=lambda self, row: self.writer.writerow([f.encode('utf8') for f in self._dict_to_list(row)])
with open("Artikel.csv", "ab") as csvfile:
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames, delimiter=";") 
    writer.writerow({"Fachkoordinate": entryKoordinate.get(), "Artikelnummer": entryNumber.get()})
Zum Code: vermeide verschachtelte Funktionen, und die damit verbundenen quasi-globalen Variablen.
Die Funktion `check` bekommt die Variablen `entryNumber`, `entryKoordinate`, und `eingabeFenster` aus dem Nichts, das sollten Parameter der Funktion sein.
Komplexere GUI-Programme brauchen zwangsläufig Klassen-Definitionen.
Warum benutzt Du zum Lesen der csv-Datei nicht auch das csv-Modul?
Der `in`-Vergleich ist zu großzügig, da in Spalte 1 entryKoordinate und in Spalte 2 entryNumber stehen müßte, und nicht irgendwo.
Dadurch dass Du per `break´ die for-Schleife verläßt, wird das Schreiben des Datensatzes in die csv-Datei nicht unterbunden.
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Zubi: Wie kommt denn der Wert `csv` bei Dir zustande? Wenn das nicht das `csv`-Modul aus der Standardbibliothek ist, sollte man das erwähnen. Wenn Du `unicodecsv` verwendest, dann gibst Du die Kodierung an der falschen Stelle an. Die Dateien müssen dann im Binärmodus geöffnet werden und die Kodierung wird bei den Writer/Reader-Objekten angegeben.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten