Probleme mit cxfreeze und Python 3.1
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:
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:
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))
Ausschnitt aus der (eigentlich formatierten) Ausgabe:
Code: Alles auswählen
b'Rechtwinkligkeit \x81berpr\x81fen 3'
b'H\x94he berechnen 4
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<<
Mit Version meinst du wahrscheinlich Sprachversion Ausserdem kann man in der Windows-Eingabeaufforderung mit chcp das Encoding ändern.Nö ... das Encoding der (Windows) Eingabeaufforderung (via: cmd.exe) ist abhängig von Deiner Windows-Version.
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')
äöü?
Code: Alles auswählen
>>> import locale, sys
>>> print('\u00e4\u00f6\u00fc\ufffe'.encode(encoding, 'replace'))
b'\x84\x94\x81?'
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'))
äöü?
@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`.
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.
Stimmt, da müsste in meinen Beispielen noch ein `or sys.getdefaultencoding()`o.ä. hintendran.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`.
könnte man nicht str überschreiben und dann in die __init__ einfach ein self.decode(xyz) ?
the more they change the more they stay the same
@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.
Mir tuts auch Leid, ich hab nicht mitgedacht
the more they change the more they stay the same
Hmm. Eher würde ich eine eigene print-Funktion verwenden:
(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.
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)
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.
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.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...
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
Nee, ich hätte jetzt das selbe geschrieben wenn ich nicht vorher F5 gedrückt hätte.
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
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
1. Ich bin zu dumm, die Funktion zu verstehen
2. Die Python-Entwickler wollen einen verarschen
3. Die Funktion ist leider kaputt
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!
Mein cxfreeze funktioniert wieder und ich bin ansonsten recht glücklich
Mein cxfreeze funktioniert wieder und ich bin ansonsten recht glücklich