Zipfile.write UnicodeDecodeError

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
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Ich habe in Django beim Erstellen einer ZIP-File folgenden Fehler:

UnicodeDecodeError at /admin/immobilien/property/add/
'ascii' codec can't decode byte 0xac in position 10: ordinal not in range(128)

Dazugehöriger Code:

Code: Alles auswählen

        # ZIP-Archiv aus XML-Datei und Bildern wird für IS24-Export erzeugt
        export_zip = '%s' % (object_id) + EXPORT_ZIP
        z = (
            zipfile.ZipFile(os.path.join(EXPORT_PATH, '%s/' % (object_id), export_zip), 
            "w")
        )
        z.write(f.name, os.path.basename(f.name)) # DIESE ZEILE VERURSACHT FEHLER!!!
Ich bin gerade doch sehr ratlos, da dieser Fehler bisher eigentlich in meiner Testumgebung nicht auftrat und ich heute nur mein DjangoModel geändert habe.

Was könnte das sein bzw. wo könnte der Fehler sein?
Ist das ein Bug in ZipFile?

Habe nämlich folgendes gefunden:
http://bugs.python.org/issue1734346

Irgendjemandem hier muss das doch sicher auch schon unter die Augen gekommen sein und wissen wie man gegensteuern kann. Ich wäre wirklich unendlich dankbar über Hilfe.
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Im Internet habe ich folgenden Lösungsansatz gefunden:
http://bytes.com/groups/python/24652-un ... e-problems

Und nun habe ich die relevante Zeile wie folgt geändert und es funktioniert:

Code: Alles auswählen

z.write(f.name, os.path.basename(f.name).encode("latin-1"))
Trotzdem würde ich gerne wissen, ob dieser Fehler bekannt ist und es wirklich ein Bug in zipfile ist!?

Außerdem bin ich mit der encode-Methode nicht ganz vertraut. Was bewirke ich mit der Änderung? Wandle ich den utf-8 String in einen latin-1 String um?

Weiterhin trat der Fehler an anderer Stelle beim Zipfile.write auch ohne das .encode nicht auf. Wieso dann in dem Code oben? Muss ich das verstehen? Ich sollte vielleicht ergänzen, dass das f von f.name ein File-Objekt ist falls das relevant ist.
Ich würde einfach gerne wissen wieso, wann uns aus welchen Gründen dieser Fehler auftritt????
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hallo ferix,

suche mal im Board nach Unicode und Fehler oder so. Da findest Du zig Threads dazu. Hilfreich dafür ist u.a. die Seite im wiki! (Auf die wird auch gerne verwiesen).

Mir haben auch die Slides von Leonidas sehr geholfen. Müßteste mal im wiki nach den Usergruppe München gucken. Dort sind die alten Vorträge imho verlinkt.
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Vielen Dank!

Aber ich glaube das erklärt meine Fragen nur bedingt.
Ich denke das hängt durchaus mit dem zipfile Modul zusammen, weil ich ansonsten bisher immer so "sauber" gearbeitet habe, dass mir der Fehler auch noch nie unter die Augen gekommen war bis dahin.

Und das fuchst mich eben so, dass ich nicht genau weiß wie der Fehler an der einen Stelle zustande kam und wieso er auch nur genau an dieser einen Stelle war und bei der anderen nicht.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Naja, ZIP-Dateien enthalten ja auch nur Bytestrings, also muss dein Unicode-String irgendwie enkodiert werden, damit er als Bytestring repräsentierbar ist. Da du aber nicht angibst, wie das gehen soll, nimmt Python an, das es nach ASCII enkodiert werden soll. Wenn du dann im String Umlaute oder ähnliches hast, crasht dann das Programm, da Umlaute nicht in ASCII darstellbar sind.

Das ist kein Problem des Zipfile-Moduls an sich. Das ist generell ein Problem, dass Unicodestrings nur eine Folge von Codepoints sind und diese keine definierte Bytedarstellung haben. Aber Festplatten, Netzwerkkarten, Laufwerke etc. arbeiten nunmal mit Bytes.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Hey Leonidas,

einmal mehr vielen Dank für deine Erklärungen ;)

Ich habe durch die Folien der UserGroup München und herumprobieren aber in den letzten Minuten auch Licht ins Dunkle bekommen.

Jetzt aber noch ein paar kleine Verständnis-Fragen:
Die Funktionen encode/decode dienen also dazu Unicode in Byte-Code eines bestimmten Zeichensatzes (utf-8, ...) zu kodieren und umgekehrt??

Wenn ich einen String in Python 2.5 ohne das u"string" anlege, also "string", ist dieser String direkt in utf-8 Byte-Code abgelegt und kein Unicode???

Und verdammt die 3. Frage hab ich jetzt vor lauter lauter vergessen ^^
Aber ich möchte mit diesen Fragen jetzt einfach nochmal mein Verständnis prüfen.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ferix hat geschrieben:Ich habe durch die Folien der UserGroup München und herumprobieren aber in den letzten Minuten auch Licht ins Dunkle bekommen.
Freut mich, dass dir die Folien geholfen haben.
ferix hat geschrieben:Jetzt aber noch ein paar kleine Verständnis-Fragen:
Die Funktionen encode/decode dienen also dazu Unicode in Byte-Code eines bestimmten Zeichensatzes (utf-8, ...) zu kodieren und umgekehrt??
Ja, genz genau.
ferix hat geschrieben:Wenn ich einen String in Python 2.5 ohne das u"string" anlege, also "string", ist dieser String direkt in utf-8 Byte-Code abgelegt und kein Unicode???
Ja, dieser wird exakt so geladen wie er in der Datei steht, als Sequenz von Bytes (und auch wenn du ``# -*- coding: utf-8 -*-`` in die Datei schreibst ändert sich das nicht - du kannst dort beliebige Bytes in beliebiger Reihenfolge reinsetzen). Bei Unicode-Strings (und wenn du ab Python 2.6 aus ``__future__`` die Unicode-Literale importierst) wird dieser String ebenfalls so wie er in der Datei steht gelesen, aber zusätzlich wird dann ein (implizites) decode('das_encoding_aus_dem_header') auf den Strings aufgerufen, so dass du automatisch Unicode-Objekte bekommst.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Super vielen Dank dann weiß ich jetzt, dass ich alles soweit verstanden habe :)
Jetzt muss ich noch Rückmeldung im PDF-Thread geben ;)
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Ach eine kleine Frage ist mir noch eingefallen nach der ganzen Studie ^^

Es ist am "saubersten", wenn man Unicode-Strings verwendet und beim Schreiben in eine Datei dann ein encode.Zeichensatz macht!?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

ferix hat geschrieben:Es ist am "saubersten", wenn man Unicode-Strings verwendet und beim Schreiben in eine Datei dann ein encode.Zeichensatz macht!?
Ja. In den Folien habe ich auch ``codecs.open`` vorgestellt, was quasi das gleiche ist wie ``open()`` nur dass es Unicodestrings entgegennimmt und dann selbst enkodiert. So kann man direkt Unicode in Dateien schreiben und das ``codecs.open``-Objekt kümmert sich um das Enkodieren von selbst.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Jetzt will ichs aber wissen :D

Bei der Erstellung der __unicode__() - Methode in Django. Reicht hier

Code: Alles auswählen

return self.title
oder

Code: Alles auswählen

return "%s %s" % (self.vorname, self.nachname)
aus, weil die Model-Variablen ohnehin als Unicode gespeichert werden oder sollte man

Code: Alles auswählen

return u"%s" & (self.title)
oder

Code: Alles auswählen

return u"%s %s" % (self.vorname, self.nachname)
machen?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Na probiere es doch aus. Baue dir eine Klasse die __unicode__ definiert und spiele ein wenig mit dem String-Formatting. Das geht auch recht bequem direkt im Interpreter.

Generell solltest du aber bei deinen Funktionen - gerade im Zusammenspiel mit Django - immer Unicode ausgeben. Nur so als Tipp.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ferix
User
Beiträge: 128
Registriert: Sonntag 1. Juni 2008, 18:21

Danke für den Tipp!

Ja mit dem python-Interpreter habe ich seit dem ersten Eintrag zu diesem Thema rumprobiert, was mir wirklich sehr geholfen hat.
Antworten