Mich ärgert es immer wieder, wie umständlich man bei Python mit Umlauten umgehen muss. Überhaupt dann, wenn man Programme für Windows, Linux und Cygwin schreiben möchte UND diese eventuell auch mit cx_freeze oder py2exe packen möchte.
Dann gibt es noch die verschiedensten Editoren, Interpreter und IDEs in denen die Programme ja auch laufen sollten. (python, ipython, PyShell, IDLE, WingIDE,...)
Ich habe zwar den Hinweis bekommen, dass Python versucht, beim Schreiben in die Konsole das richtige Encoding zu verwenden wenn man einen Unicode-String übergibt, aber das funktioniert bei mir die meiste Zeit NICHT. Auf dieses anscheinend willkürliche Verhalten bei Unicode-Strings kann ich nicht setzen.
Deshalb habe ich mich mit einem Workaround befasst, der in den meisten Fällen funktionieren sollte. Allerdings ist dieser Ersatz ziemlich umständlich und ich kann ihn auch nicht überall testen. Aber zumindest habe ich es versucht.
Unten stehender Code wurde von mir bereits unter folgenden Bedingungen getestet:
- Windows 2000 - Python 2.4.3
- Windows 2000 - Python 2.4.3 - IDLE 1.1.3
- Windows 2000 - Python 2.4.3 - WingIDE 2.1.0-1
- Windows 2000 - Cygwin - Bash 3.0 - Python 2.4.1 (GCC)
- Windows 2000 - Cygwin - Bash 3.0 - Python 2.4.3 (MSC)
- Debian 3.1 Linux (locale: de_AT@euro) - Python 2.3.5
- Debian 3.1 Linux (locale: de_AT@euro) - Python 2.4.1
- Gentoo linux (local: de_AT.utf8) - Python 2.4.2 - (# -*- coding: utf-8 -*-)
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
# Lizenz: ohne Einschränkungen frei
import os
import sys
import codecs
# Imports für cx_freeze:
import encodings, encodings.ascii, encodings.utf_8, \
encodings.iso8859_1, encodings.iso8859_15
try:
import encodings.mbcs, encodings.cp850
except:
pass
# sys.stdout umleiten, damit Umlaute korrekt angezeigt werden.
#(funktioniert auch mit Idle und cx_freeze)
out_enc = ""
if sys.platform.startswith("win"):
out_enc = getattr(sys.stdout, "encoding", None) or \
sys.getfilesystemencoding() or "cp850"
elif sys.platform.startswith("linux"):
out_enc = getattr(sys.stdout, "encoding", None) or \
sys.getfilesystemencoding() or \
os.popen("locale | grep 'LC_MESSAGES'").read().strip().split("=")[1]
else:
out_enc = getattr(sys.stdout, "encoding", None) or \
sys.getfilesystemencoding() or ""
if out_enc.upper() in ("", "ASCII", "US-ASCII", "ANSI_X3.4-1968", "POSIX"):
out_enc = "raw_unicode_escape"
sys.stdout = codecs.getwriter(out_enc)(sys.stdout)
if __name__ == "__main__":
# testen
print "out_enc:", out_enc
print u"printtest öäüß"
sys.stdout.write(u"stdouttest: äüöß\n")
lg
Gerold
PS: Für sys.stderr habe ich noch überhaupt keine Lösung gefunden. Gibt es eine allgemein verwendbare Möglichkeit, das Encoding von sys.stderr raus zu bekommen?
- Edit: try-except um einen Import gelegt.
- Edit: Sonderfälle abgefangen
- Edit: .split("=")[1] hinzugefügt
- Edit: "POSIX" hinzugefügt
- Edit: auch für Linux ein sys.getfilesystemencoding() eingebaut
- Edit: "cygwin" raus geschmissen, da es von den Ausnahmefällen abgedeckt wird.
- Edit: Ab jetzt wird bei unbekannten Betriebsystemen zumindest versucht, das Encoding raus zu bekommen.