decode Umlaute Python 3.2

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.
Antworten
Herr_M_aus_R
User
Beiträge: 6
Registriert: Montag 7. November 2011, 11:53

Hallo,

ich habe ein Problem mit Umlauten. Habe zwar hier schon einiges gelesen, aber ich komme leider trotzdem nicht klar.
Hier ein Mini-Programm, das das Problem zeigt (Python 3.2 !!!):
import subprocess, sys

print (sys.stdout.encoding )
print (sys.getfilesystemencoding ())

with subprocess.Popen("ping -n 1 1.2.3.4", stdout=subprocess.PIPE, shell=True) as proc:
# pingErg = proc.stdout.read()
pingErg = proc.stdout.read().decode (encoding="utf-8", errors="ignore")
print (pingErg)

Das ergibt diese Ausgabe: (die Umlaute fehlen)
cp1252
mbcs



Ping wird ausgefhrt fr 1.2.3.4 mit 32 Bytes Daten:





Zeitberschreitung der Anforderung.





Ping-Statistik fr 1.2.3.4:


Pakete: Gesendet = 1, Empfangen = 0, Verloren = 1 (100% Verlust),

Ich habe schon alle möglichen Codec-Angaben versucht, immer dasselbe Ergebnis. Mit errors = strict erhalte ich einen Laufzeitfehler
Wird die Zeile
pingErg = proc.stdout.read()
verwendet, erhalte ich folgende Ausgabe, also \x81 für 'ü', ich schließe daraus, dass es ASCII ist:
cp1252
mbcs
b'\r\r\nPing wird ausgef\x81hrt f\x81r 1.2.3.4 mit 32 Bytes Daten:\r\r\n\r\r\nZeit\x81berschreitung der Anforderung.\r\r\n\r\r\nPing-Statistik f\x81r 1.2.3.4:\r\r\n Pakete: Gesendet = 1, Empfangen = 0, Verloren = 1 (100% Verlust),\r\r\n'

Hat jemand eine Idee, was ich machen kann?

Vielen Dank

Martin
BlackJack

@Herr_M_aus_R: Wenn ein Wert über 127 (0x7F) in den Daten ist, dann kann es kein ASCII sein und ein 'ü' ist in ASCII nicht enthalten. Du müsstest halt schauen was für eine Kodierung das ``ping`` liefert. Wahrscheinlich die, welche *dessen* “Umgebung“ verwendet wird, also die Windows-Eingabeaufforderung. Die müsstest Du heraus finden können, wenn Du Dir mal `sys.stdout.encoding` von einem in eben dieser Eingabeaufforderung gestarteten Programm anschaust.
Herr_M_aus_R
User
Beiträge: 6
Registriert: Montag 7. November 2011, 11:53

Hallo BlackJack,

ja, das habe ich in einem Forumsbeitrag gelesen.
Im Programm wird des Encoding der Eingabeaufforderung mit
print (sys.getfilesystemencoding ())
abgefragt und angezeigt, Ergebnis ist mbcs.
Das habe ich auch probiert und es kam trotzdem kein 'ü' raus.
Ich habe auch latin_1, ascii, cp850 usw probiert.
Wie heißt denn die "ASCII"-Tabelle, die auch Werte über 127 enthält ? Früher hat man mit diesen Werten schöne Kästchen auf dem Textbildschirm gezeichnet.

Gruß

Martin
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Und du kannst dir nicht vorstellen, dass das Encoding des Dateisystems und die der Eingabeaufforderung gar nichts miteinander zu tun haben? ;-) Probiere einfach mal BlackJacks Hinweis bezüglilch `sys.stdout.encoding` aus, das sollte dein Problem lösen.
Das Leben ist wie ein Tennisball.
BlackJack

@Herr_M_aus_R: Mit `sys.getfilesystemencoding()` bekommt man die Kodierung des Dateisystems heraus und nicht die der Eingabeaufforderung. Streng genommen noch nicht einmal das, weil in einem System ja auch mehrere Dateisysteme mit verschiedenen Kodierungen eingebunden sein können. Wenn man wissen möchte was am anderen Ende von `sys.stdout` verwendet wird, dann muss man sich das `encoding`-Attribut anschauen. Wobei das auch nur auf etwas anderes als `None` gesetzt wird, wenn Python das ermitteln konnte. Darauf kann man sich nicht verlassen. Es läuft letztendlich darauf hinaus, dass man immer eine Ausweichlösung implementieren sollte, bei der der Benutzer des Programms eine Kodierung angeben kann.

Wenn Du das wirklich alles probiert hast, dann stimmen die Daten nicht, die Du weiter oben gezeigt hast. Die sollten sich nämlich, zumindest was Du gezeigt hast, beispielsweise mit ``cp850`` dekodieren lassen.

*Die* Zeichenkodierungstabelle die auch Werte über 127 enthält, gibt es nicht. Das tun nämlich fast alle gängigen ausser ASCII.
Herr_M_aus_R
User
Beiträge: 6
Registriert: Montag 7. November 2011, 11:53

Hallo zusammen
und danke für eure Antworten.
zuerst: es geht jetzt, cp850 ist richtig, ich könnte schwören, dass ich das auch schon probiert hatte...

Dann noch:
Ich hatte dieses gelesen: http://wiki.python-forum.de/Von%20Umlau ... 0Encodings
und daraus sind auch die beiden Zeilen ganz vom Anfang des Skripts:
print (sys.stdout.encoding )
print (sys.getfilesystemencoding ())
Aus dem Text hatte ich geschlossen, dass getfilesystemencoding das richtige ist (Encoding der Kommandozeile), ist aber auch egal, weil keines der Ergebnisse cp1252 und mbcs richtig funktionierte.
Ich habe mich an alte DOS und Win 3.1 Zeiten erinnert und da gab es die copdepage 850, wenn man die nicht gewählt hatte, kamen auch immer falsche Zeichen raus. Ich dachte, das hier auch versucht zu haben... ts-ts-ts

nochmal danke für die Hilfe

Gruß

Martin
Herr_M_aus_R
User
Beiträge: 6
Registriert: Montag 7. November 2011, 11:53

Oh je, doppelt Asche auf mein Haupt !
Gerade habe ich nochmal genauer nachgelesen im Beitrag von BlackJack:
" sys.stdout.encoding` von einem in eben dieser Eingabeaufforderung gestarteten Programm anschaust "
Dabei kommt tatsächlich cp850 raus. (Ich arbeite in der Python IDLE)
Bleibt die Frage, wie ich das unabhängig von der Ausführungsbasis bestimmen kann

Gruß
Martin
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Herr_M_aus_R hat geschrieben:Dabei kommt tatsächlich cp850 raus. (Ich arbeite in der Python IDLE)
Bleibt die Frage, wie ich das unabhängig von der Ausführungsbasis bestimmen kann
Was meinst du mit deiner letzten Bemerkung? `sys.stdout.encoding` gibt dir das aktuelle Encoding. Das musst du natürlich so als Variable verwenden und darfst nicht überall per Hand das Encoding noch einmal eintragen.
Das Leben ist wie ein Tennisball.
Herr_M_aus_R
User
Beiträge: 6
Registriert: Montag 7. November 2011, 11:53

Hallo
Was meinst du mit deiner letzten Bemerkung?
Die Zeile
print (sys.stdout.encoding )
ergibt cp1252, wenn von IDLE aus gestartet und cp850, wenn aus einer DOS-Box gestartet.

Gruß
Martin
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Und wo ist da genau das Problem? Es gibt nicht das eine systemweite Encoding. Wenn du bei der Ausgabe `sys.stdout.encoding` verwendest, dann musst du dir darum im Prinzip auch keine Gedanken mehr machen, da alles transparent im Hintergrund erledigt wird.
Das Leben ist wie ein Tennisball.
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Herr_M_aus_R hat geschrieben:Die Zeile
print (sys.stdout.encoding )
ergibt cp1252, wenn von IDLE aus gestartet und cp850, wenn aus einer DOS-Box gestartet.
Daraus folgt doch dann, dass diese Zeile

Code: Alles auswählen

pingErg = proc.stdout.read().decode(encoding="utf-8", errors="ignore")
dynamisch ermtiteln muss welches Encoding vorhanden ist und damit eher so aussehen sollte

Code: Alles auswählen

ping_ergebnis = proc.stdout.read().decode(encoding=sys.stdout.encoding, errors="ignore")
Herr_M_aus_R
User
Beiträge: 6
Registriert: Montag 7. November 2011, 11:53

Hallo,

also insgesamt so:

Code: Alles auswählen

import subprocess, sys

print (sys.stdout.encoding )
print (sys.getfilesystemencoding ())

with subprocess.Popen("ping -n 1 1.2.3.4", stdout=subprocess.PIPE, shell=True) as proc:
#    pingErg = proc.stdout.read()
    pingErg = proc.stdout.read().decode (encoding=sys.stdout.encoding, errors="ignore")
print (pingErg)    
Das funktioniert in der DOS-Box, aber nicht in IDLE (d.h.keine 'ü'). Das liegt daran, dass in der IDLE sys.stdout.encoding cp1252 ergibt und nicht cp850.
Man müßte also von IDLE aus ermitteln, was sys.stdout.encoding in der DOS-Box ergibt, so ist gerade mein Verständnis.
Ist aber für mich im Moment eher ein akademisches Problem, wenn ich cp850 einsetze geht es für mich prima. Aber international gesehen ist das natürlich keine Lösung.

Gruß
Martin
Antworten