cgi.FieldStorage und Python3

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

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?
Bottle: Micro Web Framework + Development Blog
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Defnull hat geschrieben:Wie gesagt, es sollte klappen. Keine Ahnung, ob es das in freier Wildbahn auch tut. Meinungen/Ideen dazu?
So wie du es beschreibst: Bug melden.
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Das Problem ist seit Python3.0 bekannt. Auf WSGI1.1 oder 2.0 wartet man seit dem vergeblich. Auf angepasste Module ebenfalls. Python3 ist einfach noch nicht fertig.
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Kenne mich in den tiefen der Thematik nicht aus...

Wenn ich es richtig verstehe, willst du cgi.FieldStorage so belassen wie es ist und der Work-a-round drum rum bauen, oder? Wäre es da nicht klüger cgi.FieldStorage neu zu implementieren bzw. zu ändern?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

jens hat geschrieben:Kenne mich in den tiefen der Thematik nicht aus...

Wenn ich es richtig verstehe, willst du cgi.FieldStorage so belassen wie es ist und der Work-a-round drum rum bauen, oder? Wäre es da nicht klüger cgi.FieldStorage neu zu implementieren bzw. zu ändern?
Nicht unbedingt, da cgi.FieldStorage 1000 Sonderfälle und Tricks kennt und fest verzahnt mit anderen Modulen ist. Bei jedem anderen Projekt würde ich dir zu stimmen, aber bei Bottle wäre dann das halbe Framework eine neu-Implementation von cgi.FieldStorage. Das möchte ich, wenn es geht, vermeiden.
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich meinte auch nicht, nur in Bottle eine neue Version von cgi.FieldStorage mit zu liefern, sondern wirklich die Version in Python zu verbessern. Bis in Python dann eine funktionierende Version vorliegt, kannst du ja den work-a-round nutzten...

Btw. wie machen es die anderen Frameworks?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Was spricht denn gegen einen Workaround? So wie Defnull das beschrieben hat, kann man diesen ja später bei einer Lösung für FieldStorage in Py 3.x den Workaround einfach entfernen - also imho eine gute Idee für die aktuelle Lage.

@jens: Bei Pylons habe ich nichts explizites zu Python 3 gefunden, bei Django steht, dass Python 3 nicht wirklich unterstützt wird (was Du ja wohl weißt :-) ) und bei TurboGears wird es explizit ausgeschlossen. Auch wenn das nicht alles abdeckt, so deutet es eben an, dass viele hier keinen Workaround betreiben und lieber ganz auf Python 3 Unterstützung verzichten.

Da ich mich so tief in der Materie auch nicht auskenne, weiß ich nicht, ob so eine Lösung wie Defnull sie beschrieben hat bei größeren Projekten zu Problemen führen kann. Vermutlich will eben kein größeres Framework sein eigenes Süppchen kochen...
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Sieht so aus, als ob es Zeit für ein PEP wäre, der das Problem am Ursprung löst.
Antworten