Allgemeine Lösung für Umlautprobleme?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hi!

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")
Bitte probiert diesen Code mit eurem Betriebssystem aus und teilt mir mit, ob es damit Probleme gibt. Vielleicht weiß jemand auch eine bessere Lösung --> dann sagt sie mir. Bitte! Ich suche schon lange nach einer guten Lösung. :roll: Auch wenn ich mich damit blamiere, aber ich habe bis auf oben stehende Lösung noch nicht raus bekommen, wie man es besser machen könnte.

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.
Zuletzt geändert von gerold am Dienstag 22. Mai 2007, 13:50, insgesamt 11-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

...
Oben stehenden Code habe ich unter Windows 2000 auch mit cx_freeze ausprobiert.

Zum Freezen habe ich folgende Batch-Datei verwendet:

Code: Alles auswählen

REM  --------------------------------------------------
REM   Erstellt aus dem PYTHONFILE eine ausführbare EXE
REM  --------------------------------------------------

SET PROJECTDIR="C:\Dokumente und Einstellungen\Gerold\Desktop\umlauttest"
SET PYTHONFILE="umlauttest.py"

CD /D %PROJECTDIR%

DEL %PROJECTDIR%\bin\win\msvcr71.dll
DEL %PROJECTDIR%\bin\win\python24.dll
DEL %PROJECTDIR%\bin\win\umlauttest.exe

CP %SystemRoot%\system32\msvcr71.dll %PROJECTDIR%\bin\win\

FreezePython.exe --install-dir=%PROJECTDIR%\bin\win %PYTHONFILE%

PAUSE
Zumindest auf dem gleichen Computer lässt sich das Programm in der Konsole aufrufen und liefert korrekt angezeigte Umlaute.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Nachdem ich encodings.mbcs auskommentiert habe (das kommt davon wenn man irgendwelche unnötigen Module importiert nur um Freezer glücklich zu machen) lief es bei mir auch, zumindest auf meinem Ubuntu. Auf dem Debian ging es nicht, dort dam als Out-Encoding aber immerhin ANSI_X3.4-1968 raus.

Systeme:
Ubuntu Linux 6.06 (locale: en_AU.UTF-8) - Python 2.4.3
Debian GNU/Linux 3.1 (locale: POSIX) - Python 2.4.3
Zuletzt geändert von Leonidas am Montag 21. Mai 2007, 22:46, insgesamt 1-mal geändert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hi Leonidas!
Leonidas hat geschrieben:Nachdem ich encodings.mbcs auskommentiert habe
Das kommt davon, wenn ich nach dem Testen noch ein paar Module importiere... :? Ich werde wohl noch ein try-except einbauen müssen.

Leonidas hat geschrieben:Auf dem Debian ginbg es nicht, dort dam als Out-Encoding aber immerhin ANSI_X3.4-1968 raus.
[...]Debian GNU/Linux 3.1 (locale: POSIX) - Python 2.4.3

Was könnte man tun, damit es unter Linux auch dann noch funktioniert, wenn als "locale" *POSIX* eingestellt ist?

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
Damaskus
Administrator
Beiträge: 995
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

Windows XP - Python 2.4.3
Windows XP - Python 2.4.3 - IDLE
Windows XP - Python 2.4.3 - WingIDE 2.1.x

funktioniert. Mit Windows Vista werd ichs am Wochenende mal testen.

Gruß
Damaskus
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Unter Suse 10.0 mit Python 2.4.1 und mit LANG=en_US.UTF-8 klappts.
Unter Slax 5.1.6 kam als Out-Encoding auch immer ANSI_X3.4-1968 raus. Allerdings ist dort LANG=en_US, und locale.getdefaultlocale() liefert (None, None) :?:.

Du solltest noch irgendwas fuer den Fall tun, dass man was anderes als die vorgesehenen Betriebssysteme benutzt. Denn NameError: name 'out_enc' is not defined ist irgenwie bloed...
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Rebecca hat geschrieben:Unter Slax 5.1.6 kam als Out-Encoding auch immer ANSI_X3.4-1968 raus. Allerdings ist dort LANG=en_US, und locale.getdefaultlocale() liefert (None, None) :?:.

Du solltest noch irgendwas fuer den Fall tun, dass man was anderes als die vorgesehenen Betriebssysteme benutzt. Denn NameError: name 'out_enc' is not defined ist irgenwie bloed...
Hi!

@Leonidas, Damaskus, Rebecca: Danke schon mal fürs testen.

@Leonidas, Rebecca: Bitte noch einmal ausprobieren? Ich habe etwas eingebaut, was ich nicht testen kann. Bei mir sind überall "locales" eingestellt.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Cool, unter Slax geht's jetzt. out_enc ist nun raw_unicode_escape. Das ganze ist uebrigens Python 2.4.1.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Rebecca hat geschrieben:Cool, unter Slax geht's jetzt.
Merci :-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Naja, jetzt wird das Programm zwar nicht durch eine Exception beendet, sondern es kommt raw_unicode_escape. Dann kommen die Zeichen, die aber dann als Kästchen mit Fragezeichen dargestellt werden - könnte auch eine Inkompatibilität mit dem Encoding von dem Rechner auf dem ich SSH ausführe.

Dafür funktioniert print 'äöü' im Interpreter dagegen tadellos.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Leonidas hat geschrieben:Kästchen mit Fragezeichen
[...]
Dafür funktioniert print 'äöü' im Interpreter dagegen tadellos.
Hi Leonidas!

Vielen Dank für den Test. Allerdings weiß ich nicht, was ich verändern könnte, damit es besser funktioniert.

Wenn du Umlaute siehst, dann liegt es wahrscheinlich nicht an der Schrift. Mehr fällt mir aber dazu auch nicht ein. Du verwendest ein Encoding, das mit Umlauten nichts anfangen kann, kannst aber trotzdem Umlaute sehen... verstehen tu ich es nicht.

Ich bitte weiterhin alle hier im Forum, sich daran zu beteiligen und einen Tipp abzugeben, wie es besser laufen könnte, was man verbessern und verändern könnte.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Hab das ganze mal auf AIX laufen lassen :twisted: . Bekomme dann natuerlich auchraw_unicode_escape, und statt der vier Umlaute zwei Kaestchen. Da ich mich per ssh eingeloggt habe, habe ich gedacht, vielleicht geht irgendwo zwischen meinem xterm und der AIX-Shell was verloren. Ich kann aber in der Shell per echo und im Interpreter per print Umlaute ausgeben lassen. Ich bekomme allerdings den Quellcode nicht richtig angezeigt (auch immer mit Kaestchen an den entprechenden Stellen), weder mit more noch mit Emacs oder vi. Im Emacs bekomme ich auch manuell ueberhaupt keine Sonderzeichen zustande.

Python-Version ist 2.2, locale.getdefaultlocale liefert ['en_US', 'ISO8859-1'].

Naja, dieses daemliche AIX geht mir sowieso total auf die Nerven. :?

So, jetzt geht's ab ins Wochenende! 8)
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Rebecca hat geschrieben:Hab das ganze mal auf AIX laufen lassen
Hi Rebecca!

Was bekommst du zurück, wenn du ``sys.platform`` eingibst?
Normalerweise könnte ich dieses OS ja sicher gleich wie Linux behandeln. Wenn ich weiß, was bei ``sys.platform`` raus kommt, dann mach ich das.

Bei ``ISO8859-1`` könnte das funktionieren.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
CrackPod
User
Beiträge: 205
Registriert: Freitag 30. Juni 2006, 12:56

(K)ubuntu 5.10; KDE: 3.5.0; Kernel 2.6.12-10-686; Architektur: i686

Code: Alles auswählen

IDLE 1.1.2      
>>> ================================ RESTART ================================
>>> 
out_enc: utf-8
printtest öäüß
stdouttest: äüöß

Code: Alles auswählen

$ python UmlauteTest.py
out_enc: UTF-8
printtest öäüß
stdouttest: äüöß
Also ein Terminal und IDLE Test.
Wie kann ich das dann in meine Programme einfügen? Kann ich das als Modul importieren oder muss ich das an den Anfang von jedem Programm schreiben?
Und noch ne Frage: Lässt sich das auch als Lösung für eine Eingabe verwenden? Dann gibts keine Probleme mehr dafür
Greetz
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

CrackPod hat geschrieben:(K)ubuntu 5.10; KDE: 3.5.0; Kernel 2.6.12-10-686; Architektur: i686
[...]
Kann ich das als Modul importieren?
[...]
Lässt sich das auch als Lösung für eine Eingabe verwenden?
Hi CrackPod!

Danke, für den Test.

Ja, es lässt sich einfach als Modul importieren. Und wenn man kein cx_freeze einsetzt, dann kann man die speziellen Imports für cx_freeze auch weg lassen.

Das ist noch keine Lösung für sys.stdin oder sys.argv. Allerdings habe ich vor, sobald ich herausgefunden habe, ob das hier eine gute Lösung ist, auch sys.stdin so umzuleiten.

sys.stderr ist irgendwie ein Sonderfall. Da bekomme ich meistens kein Encoding dafür raus. Du siehst, es wird noch ein Weilchen dauern bis es eine Lösung wird, die man allgemein empfehlen kann. Vielleicht ist in Python auch schon alles eingebaut was man braucht und ich habe es nur noch nicht kappiert. -- Das kann auch noch sein.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
CrackPod
User
Beiträge: 205
Registriert: Freitag 30. Juni 2006, 12:56

da müsste man sich mal in englischen Foren umschaun... Obwohl-.- Die haben das Problem ja nich und ich denk, denen wird das evtl auch egal sein ;)
Aber dann würd doch was beim CookBook stehen oder so?! Ich mein, Russen oder Tschechen oder Araber haben das Problem ja auch...

Also ich denk, ganz ehrlich gesagt nich, dass Python schon was dabei hat, sonst hätte das sicher schon jemand gefunden und es wär bekannt.
Gibt es noch andere deutschsprachige Pythonforen. Vielleicht haben die ja User, die schon sowas gebaut haben, oder wissen, wie es geht:roll:

Greetz

P.S. Kein Problem für den Test. Kann ich mehrere Pythonversionen laufen lassen? Dann test ichs noch mit anderen Pythonversionen und wenn meine neuen Ubuntu CDs kommen, gibts auch den Test auf (K)Ubuntu 6.04 :)
Nenn mit noch ein paar IDEs mit denen Ich testen soll, dann test ich dir das auch eben noch
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

CrackPod hat geschrieben:Also ich denk, ganz ehrlich gesagt nich, dass Python schon was dabei hat, sonst hätte das sicher schon jemand gefunden und es wär bekannt.
Gibt es noch andere deutschsprachige Pythonforen. Vielleicht haben die ja User, die schon sowas gebaut haben, oder wissen, wie es geht:roll:
Nein, wir sind das einzige deutschsprachige Webforum, aber es gibt noch die Mailingliste Python-de und die Newsgroup de.comp.lang.python, ebenso den IRC-Channel #python.de auf freenode. Und es gibt Martin von Löwis ;)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
CrackPod
User
Beiträge: 205
Registriert: Freitag 30. Juni 2006, 12:56

Leonidas hat geschrieben:[...]Und es gibt Martin von Löwis ;)
Kenn ich nich, also sowohl Martin als auch Löwis :oops: - scheint aber bekannt zu sein, wenn er so explizit erwähnt wird.
Wenn er so bekannt is, schlies ich daraus, dass er sehr (sehr) gut ist. Wenn er aber so gut ist, dann müsste er sich doch auch mit dem Problem befasst haben, oder irgendwer in der Mailingliste?! Wieso gibt es dann noch keine Lösung?

Greetz
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

CrackPod hat geschrieben:Kenn ich nich, also sowohl Martin als auch Löwis :oops:
MvL ist einer der Mit-Autoren der Unicode-Implemetation in Python 2.0, zusammen mit Marc-André Lemburg (MAL) und weiteren.
CrackPod hat geschrieben:- scheint aber bekannt zu sein, wenn er so explizit erwähnt wird.
Klar, man liest immer wenn es Unicode-Probleme von ihm.
CrackPod hat geschrieben:Wenn er aber so gut ist, dann müsste er sich doch auch mit dem Problem befasst haben,
Hat er doch. Er hat Unicode implementiert.
CrackPod hat geschrieben:Wieso gibt es dann noch keine Lösung?
Wenns nach ihm geht, gibts schon Lösungen für Unicode-Probleme. Frag' ihn einfach mal, dann wirst du verstehen was ich meine ;)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Meine Meinung zum Thema: Es gibt keinen Weg die Kodierungen verlässlich zu raten. Man sollte es einfach lassen. Das raten meine ich. Und stattdessen als Standard ASCII oder UTF-8 benutzen und in seinen Programmen Optionen anbieten mit denen der Anwender explizit sagen kann was er haben möchte.

Dann hat man weniger Überraschungen. Mal angenommen ich benutze so ein "ratendes" Programm und lasse mir etwas auf der Konsole ausgeben und das Programm rät richtig was ich dort für eine Kodierung benutze. Dann denke ich cool, UTF-8 ist nett und leite die Ausgabe mit der Shell in eine Datei um. In dem Glauben das ich jetzt UTF-8 in der Datei habe. Aber leider rät das Programm für die Umleitung etwas anderes weil `sys.stdout.encoding` dann nämlich `None` ist. Das ist eine ziemlich doofe Überraschung. IMHO.
Antworten