Seite 2 von 2

Verfasst: Freitag 22. Januar 2010, 15:40
von Leonidas
Ja, dass es ein Unicode-String ist.

Verfasst: Freitag 22. Januar 2010, 15:42
von heiliga horsd
Ich dachte Python 3 verwendet von sich aus Unicode?

Verfasst: Freitag 22. Januar 2010, 16:07
von Leonidas
Oh, upps. Hab den Teil mit Python 3 übersehen. Dann kannst du es tatsächlich weglassen.

Verfasst: Samstag 23. Januar 2010, 16:58
von heiliga horsd
Ich habe die Vermutung, dass ich irgendwie zu blöd für so etwas bin :/
Also, ich habe die Variable encoding mit "850" belegt (das ist ja die entsprechende Kodierung für die cmd.exe, oder?) und folgenden Codeschnipsel für die Formatierte Ausgabe:

Code: Alles auswählen

print(str(Ausgabeformat.format(questiontext[x],
                                           questionvars[x])).encode(encoding))
Leider ist dann die Ausgabe nicht mehr formatiert (d.h. manche Werte fallen aus der Reihe) und Umlaute sehen nun noch grässlicher aus (H\x94he )

Ausschnitt aus der (eigentlich formatierten) Ausgabe:

Code: Alles auswählen

b'Rechtwinkligkeit \x81berpr\x81fen              3'
b'H\x94he berechnen                           4

Verfasst: Montag 25. Januar 2010, 09:40
von Masaru
heiliga horsd hat geschrieben:... Also, ich habe die Variable encoding mit "850" belegt (das ist ja die entsprechende Kodierung für die cmd.exe, oder?)...

Nö ... das Encoding der (Windows) Eingabeaufforderung (via: cmd.exe) ist abhängig von Deiner Windows-Version.

>>Masaru<<

Verfasst: Montag 25. Januar 2010, 14:09
von fhoech
Nö ... das Encoding der (Windows) Eingabeaufforderung (via: cmd.exe) ist abhängig von Deiner Windows-Version.
Mit Version meinst du wahrscheinlich Sprachversion :) Ausserdem kann man in der Windows-Eingabeaufforderung mit chcp das Encoding ändern.

In Python kommt man mit sys.stdout.encoding an das richtige für stdout, aber nur falls nicht mit locale.setlocale ein anderes Encoding festgelegt wurde (der Wert von sys.stdout.encoding ändert sich dadurch nämlich nicht, das eigentliche Encoding aber sehr wohl. Falls in der Anwendung nirgends setlocale benutzt wird, kann man natürlich direkt sys.stdout.encoding nehmen).

Das funktioniert dann für Python 2.6:

Code: Alles auswählen

>>> import locale, sys
>>> print u'\u00e4\u00f6\u00fc\ufffe'.encode(locale.getlocale()[1] or sys.stdout.encoding, 'replace')
äöü?
Aber Python 3.1 verhält sich anders:

Code: Alles auswählen

>>> import locale, sys
>>> print('\u00e4\u00f6\u00fc\ufffe'.encode(encoding, 'replace'))
b'\x84\x94\x81?'
Da fällt mir jetzt kein guter Workaround ein. Folgendes funktioniert, ist aber irgendwie umständlich:

Code: Alles auswählen

>>> import locale, sys
>>> print('\u00e4\u00f6\u00fc\ufffe'.encode(locale.getlocale()[1] or sys.stdout.encoding, 
                                            'replace').decode(sys.stdout.encoding, 'replace'))
äöü?

Verfasst: Montag 25. Januar 2010, 18:45
von BlackJack
@fhoech: `sys.stdout.encoding` geht aber auch nur, wenn Python die Kodierung irgendwie herausfinden konnte. Leitet man die Ausgabe in eine Datei um, dann ist das zum Beispiel `None`.

Verfasst: Montag 25. Januar 2010, 19:04
von heiliga horsd
Hmm, die Lösung ist ziemlich unpraktisch vom Aufwand her, außerdem werden manche Ausgaben tatsächlich in eine Datei geschrieben.... ich werds lieber hier gut sein lassen und euch für eure Hilfe danken! Ich bin inzwischen der Meinung, dass ich meine Programme nicht an die alte Software des Microsoftmonopols anpassen muss, dafür werden Leute bezahlt.

Verfasst: Montag 25. Januar 2010, 19:26
von fhoech
BlackJack hat geschrieben:@fhoech: `sys.stdout.encoding` geht aber auch nur, wenn Python die Kodierung irgendwie herausfinden konnte. Leitet man die Ausgabe in eine Datei um, dann ist das zum Beispiel `None`.
Stimmt, da müsste in meinen Beispielen noch ein `or sys.getdefaultencoding()`o.ä. hintendran.

Verfasst: Montag 25. Januar 2010, 19:32
von Dav1d
könnte man nicht str überschreiben und dann in die __init__ einfach ein self.decode(xyz) ?

Verfasst: Montag 25. Januar 2010, 20:01
von BlackJack
@Dav1d: "einfach" `str` "überschreiben"? Wie das? Was soll das bringen? Und dann müsste man überall das neue `str` verwenden, man kommt aber wohl kaum an allen Code heran, der das Original verwendet.

Verfasst: Montag 25. Januar 2010, 20:14
von Trundle
@BlackJack: Mit become.py natürlich.

Tut mir leid für den unqualifizierten Beitrag, ich konnte nicht widerstehen.

Verfasst: Montag 25. Januar 2010, 20:20
von Dav1d
Mir tuts auch Leid, ich hab nicht mitgedacht

Verfasst: Montag 25. Januar 2010, 21:03
von fhoech
Hmm. Eher würde ich eine eigene print-Funktion verwenden:

Code: Alles auswählen

import locale
import sys

def myprint(*args, **kwargs):
	stream = kwargs.get('file', sys.stdout)
	sep = kwargs.get('sep', ' ')
	end = kwargs.get('end', '\n')
	enc_in = enc_out = getattr(stream, 'encoding', locale.getpreferredencoding())
	if stream == sys.stdout:
		enc_out = locale.getlocale()[1] or enc_out
	if 'b' in stream.mode:
		sep, end = (char.encode(enc_out, 'replace') for char in (sep, end))
		stream.write(sep.join(arg if isinstance(arg, bytes) else (arg if isinstance(arg, str) else repr(arg)).encode(enc_out, 'replace') for arg in args))
	else:
		stream.write(sep.join((arg if isinstance(arg, str) else repr(arg)).encode(enc_out, 'replace').decode(enc_in, 'replace') for arg in args))
	stream.write(end)
(das geht bestimmt hübscher?)
Dieses 'print' beachtet ein eventuell per locale.setlocale geändertes Encoding von sys.stdout, wirft keine UnicodeError-Ausnahmen sondern ersetzt nicht darstellbare Zeichen mit einem Platzhalter ('\ufffe' oder '?'), kann übergebene Byte-Strings direkt in einen Stream schreiben, falls dieser im Binärmodus geöffnet wurde, und sollte sich ansonsten wie das Standard-'print' verhalten.

*edit* hatte noch einen Fehler drin, jetzt behoben.

Verfasst: Dienstag 26. Januar 2010, 10:25
von snafu
codecs.EncodedFile() mit `replace` als Wert für `error` dürfte die Anforderungen doch eigentlich erfüllen, oder? Man müsste sich nur noch eine kleine Wrapperfunktion schreiben, die immer in das gewünschte Encoding übersetzt. Dies kann man z.B. auch als Datenstrom an `print()` übergeben, so dass man die Funktion nicht komplett neu implementieren muss...

Verfasst: Dienstag 26. Januar 2010, 11:13
von fhoech
snafu hat geschrieben:codecs.EncodedFile() mit `replace` als Wert für `error` dürfte die Anforderungen doch eigentlich erfüllen, oder? Man müsste sich nur noch eine kleine Wrapperfunktion schreiben, die immer in das gewünschte Encoding übersetzt. Dies kann man z.B. auch als Datenstrom an `print()` übergeben, so dass man die Funktion nicht komplett neu implementieren muss...
Ja, daran dachte ich auch, aber es funktionierte nicht so, wie ich erwartet hatte. Kann aber gut sein, dass ich auf dem Schlauch stehe. Hier z.B.

Code: Alles auswählen

>>> import sys, codecs
>>> stdout = codecs.EncodedFile(sys.stdout, 'cp850', errors='replace')
>>> print('test', file=stdout)
TypeError: must be bytes or buffer, not str
>>> print(b'test', file=stdout)
TypeError: must be bytes or buffer, not str

Verfasst: Dienstag 26. Januar 2010, 11:17
von snafu
Nee, ich hätte jetzt das selbe geschrieben wenn ich nicht vorher F5 gedrückt hätte. ;)

Code: Alles auswählen

>>> import sys, locale, codecs
>>> f = codecs.EncodedFile(sys.stdout, locale.getpreferredencoding())
>>> f.write('bla')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.1/codecs.py", line 806, in write
    data, bytesdecoded = self.decode(data, self.errors)
  File "/usr/lib/python3.1/encodings/utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
TypeError: must be bytes or buffer, not str
>>> f.write(b'bla')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.1/codecs.py", line 807, in write
    return self.writer.write(data)
  File "/usr/lib/python3.1/codecs.py", line 356, in write
    self.stream.write(data)
TypeError: must be str, not bytes
Es gibt 3 Möglichkeiten:
1. Ich bin zu dumm, die Funktion zu verstehen
2. Die Python-Entwickler wollen einen verarschen
3. Die Funktion ist leider kaputt

Verfasst: Dienstag 26. Januar 2010, 18:21
von heiliga horsd
Wie gesagt, die Nutzer meines Programms ohne eine Python-Installation werden mit diesem Schönheitsfehler leben müssen. Ihr müsst euch also hier nicht weiter den Kopf über solche Lapalien zerbrechen! :wink:
Mein cxfreeze funktioniert wieder und ich bin ansonsten recht glücklich :)

Verfasst: Dienstag 26. Januar 2010, 18:34
von snafu
Nun ja, diese ganze Encoding-Sch*** finde ich weitaus mehr als eine Lapalie, aber sei's drum.