Damian Brunold

Umlaute bei CGI in Python 3.2

2011-06-04 17:22 Programmieren, Python, Web

In Python 3.0 und 3.1 musste ich folgendes machen, damit Umlaute korrekt behandelt werden:

sys.stdin = codecs.getreader('utf8')(sys.stdin.buffer)
sys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer)
form = cgi.FieldStorage()

Dieser Code funktioniert bei Python 3.2 nicht mehr. Der Grund dafür ist, dass Python 3.2 im cgi Modul explizit ein encoding hinzugefügt hat und dafür direkt auf sys.stdin.buffer zugreift. Der StreamReader von codecs.getreader hat aber keinen buffer. Also knallts.

Da aber das Encoding direkt angegeben werden kann, funktioniert der folgende Code:

sys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer)
form = cgi.FieldStorage(sys.stdin, encoding="utf8")

sys.stdin wird also nicht mehr gewrappt, dafür das richtige encoding in cgi.FieldStorage angegeben.

Ich habe das Ganze nun in ein Modul gepackt und je nach Version wird das korrekte Verhalten ausgeführt:

# module stdio.py
import cgi
import codecs
import sys

def is_at_least_3_2():
    return sys.version_info.major > 3 or sys.version_info.minor >= 2

def init():
    if is_at_least_3_2():
        pass
    else:
        sys.stdin = codecs.getreader('utf8')(sys.stdin.buffer)
    sys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer)

def cgi_form():
    if is_at_least_3_2():
        return cgi.FieldStorage(sys.stdin, encoding="utf8")
    else:
        return cgi.FieldStorage()

Damit sieht der Code dann so aus:

import stdio
stdio.init()
form = stdio.cgi_form()