Seite 1 von 1
Zipfile.write UnicodeDecodeError
Verfasst: Montag 22. Juni 2009, 15:23
von ferix
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.
Verfasst: Montag 22. Juni 2009, 15:50
von ferix
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????
Verfasst: Montag 22. Juni 2009, 16:23
von Hyperion
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.
Verfasst: Montag 22. Juni 2009, 17:03
von ferix
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.
Verfasst: Montag 22. Juni 2009, 18:17
von Leonidas
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.
Verfasst: Montag 22. Juni 2009, 18:55
von ferix
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.
Verfasst: Montag 22. Juni 2009, 19:07
von Leonidas
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.
Verfasst: Montag 22. Juni 2009, 19:12
von ferix
Super vielen Dank dann weiß ich jetzt, dass ich alles soweit verstanden habe

Jetzt muss ich noch Rückmeldung im PDF-Thread geben

Verfasst: Montag 22. Juni 2009, 19:53
von ferix
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!?
Verfasst: Montag 22. Juni 2009, 19:56
von Leonidas
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.
Verfasst: Montag 22. Juni 2009, 21:56
von ferix
Jetzt will ichs aber wissen
Bei der Erstellung der __unicode__() - Methode in Django. Reicht hier
oder
aus, weil die Model-Variablen ohnehin als Unicode gespeichert werden oder sollte man
oder
machen?
Verfasst: Montag 22. Juni 2009, 22:01
von Leonidas
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.
Verfasst: Montag 22. Juni 2009, 22:08
von ferix
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.