cgi.FieldStorage und Python3
Verfasst: Dienstag 10. November 2009, 21:12
Das alte Thema: cgi.FieldStorage und Python3
Wer jetzt nicht sofort das Stöhnen anfängt, dem erkläre ich das mal: cgi.FieldStorage ist dazu da, Multipart-Datenströme (z.B. File-Uploads bei HTTP) zu entschlüsseln. In Python2.x waren strings noch byte-strings und alles hat wunderbar funktioniert. In Python3 kommt cgi.FieldStorage aber plötzlich nicht mehr mit byte-strings klar, da es intern immer noch native strings (die nun aber unicode strings sind) verwendet. Infolgedessen stirbt cgi.FieldStorage, sobald man es mit Bytes füttert. Aus der Datenleitung kommen nun aber leider Bytes, was cgi.FieldStorage nutzlos für Python3 Umgebungen macht. (Von der Annahme, das die .readline() Methode des Streams einen len-Parameter unterstützt, was Socket Streams aber nicht immer tun, will ich jetzt mal gar nicht sprechen)
Ich habe für Bottle ein Workaround gebastelt. Es passiert meine Tests und sollte funktionieren, ist aber so hässlich und hacky, das ich gern noch ein paar zweite Meinungen hätte. Hier die Idee:
In Python2.x packe ich wsgi.input in einen StreamIO oder eine tempfile mit 'w+b', je nach dem wie groß der Inhalt nach Angabe von Content-Length ist. Damit umgehe ich das .readline(1234) Problem. cgi.FieldStorage wirft dann (wie erwartet) rohe string-keys und string-daten aus.
In Python3 wird wsgi.input in ein ByteIO statt StringIO verpackt. Bevor es allerdings an cgi.FieldStorage übergeben wird, kommt noch ein io.TextIOWrapper(self.body, encoding='ISO-8859-1') drum rum. Damit bekommt cgi.FieldStorage Unicode, womit es einigermaßen klar kommt und wirft unicode keys und Daten zurück. Möchte man dann an die rohen Byte-Daten ran kommen, kann man sie wieder mit 'ISO-8859-1' kodieren, da der ISO Standard bijektiv ist.
Wie gesagt, es sollte klappen. Keine Ahnung, ob es das in freier Wildbahn auch tut. Meinungen/Ideen dazu?
Wer jetzt nicht sofort das Stöhnen anfängt, dem erkläre ich das mal: cgi.FieldStorage ist dazu da, Multipart-Datenströme (z.B. File-Uploads bei HTTP) zu entschlüsseln. In Python2.x waren strings noch byte-strings und alles hat wunderbar funktioniert. In Python3 kommt cgi.FieldStorage aber plötzlich nicht mehr mit byte-strings klar, da es intern immer noch native strings (die nun aber unicode strings sind) verwendet. Infolgedessen stirbt cgi.FieldStorage, sobald man es mit Bytes füttert. Aus der Datenleitung kommen nun aber leider Bytes, was cgi.FieldStorage nutzlos für Python3 Umgebungen macht. (Von der Annahme, das die .readline() Methode des Streams einen len-Parameter unterstützt, was Socket Streams aber nicht immer tun, will ich jetzt mal gar nicht sprechen)
Ich habe für Bottle ein Workaround gebastelt. Es passiert meine Tests und sollte funktionieren, ist aber so hässlich und hacky, das ich gern noch ein paar zweite Meinungen hätte. Hier die Idee:
In Python2.x packe ich wsgi.input in einen StreamIO oder eine tempfile mit 'w+b', je nach dem wie groß der Inhalt nach Angabe von Content-Length ist. Damit umgehe ich das .readline(1234) Problem. cgi.FieldStorage wirft dann (wie erwartet) rohe string-keys und string-daten aus.
In Python3 wird wsgi.input in ein ByteIO statt StringIO verpackt. Bevor es allerdings an cgi.FieldStorage übergeben wird, kommt noch ein io.TextIOWrapper(self.body, encoding='ISO-8859-1') drum rum. Damit bekommt cgi.FieldStorage Unicode, womit es einigermaßen klar kommt und wirft unicode keys und Daten zurück. Möchte man dann an die rohen Byte-Daten ran kommen, kann man sie wieder mit 'ISO-8859-1' kodieren, da der ISO Standard bijektiv ist.
Wie gesagt, es sollte klappen. Keine Ahnung, ob es das in freier Wildbahn auch tut. Meinungen/Ideen dazu?