Encoding

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
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Guten Tag miteinander

Ich möchte aus dem Terminal heraus ein Python-Skript laufen lassen, das eine andere Datei verarbeiten soll. Dabei bekomme ich folgenden Fehler:
"UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 71: ordinal not in range(128)"
Davor stehen noch nähere Angaben zum file: "multiprocessing/process.py", line 258 in _bootstrap self.run()"

Ich habe gelesen, dass es heikel sei, das Standardencoding von python auf UTF-8 zu ändern. Daher die Frage: Wie könnte man diese Fehlermeldung umgehen?

Danke,
Marcel
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hallo,

Deine Informationen sind zu spärlich, um Dir weiterhelfen zu können.

- Was meinst Du mit "... andere Datei verarbeiten soll."? Poste doch mal den ungekürzten Traceback.
- Was meinst Du damit, "...dass es heikel sei, das Standardencoding ... auf UTF-8 zu ändern."?

Die Fehlermeldung besagt jedenfalls, dass ein Zeichen 0xc3 (195) verarbeitet werden soll, das im ascii-Zeichensatz (0 - 127) nicht enthalten ist.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
MarcelF6
User
Beiträge: 226
Registriert: Samstag 3. März 2012, 21:30

Hier der Traceback:
Process Process-1:
Traceback (most recent call last):
File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
self.run()
File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
self._target(*self._args, **self._kwargs)
File "[...]", line 109, in log_printer
sys.stdout.write(msg.encode("UTF-8"))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 71: ordinal not in range(128)
Ich habe lediglich (in einem Artikel) gelesen, dass es nicht zu empfehlen sei, das Standard-Encoding von python zu ändern...(wegen Abhängigkeiten etc.)
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hallo,

um einen bereits codierten string encodieren zu können, muss er natürlich zuerst decodiert werden. Der string, der die Fehlermeldung provoziert ist demnach bereits codiert (utf8, iso8859 etc...) und muss deshalb zuerst decodiert werden. Auf meinem System mit utf-8 Encoding sieht das so aus:

Code: Alles auswählen

>>> utf8 = 'Ich bin ein string mit Sönderzächen'
>>> print utf8
Ich bin ein string mit Sönderzächen
>>> utf8.encode('utf8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 24: ordinal not in range(128)
>>> print utf8.decode('utf8').encode('iso8859')
Ich bin ein string mit S�nderz�chen
Du versuchst also, einen bereits codierten string ('msg') nochmals zu codieren.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@MarcelF6: Was Du gelesen hast ist sicher das man `site.setencoding()` nicht verwenden sollte. Das sollte man auch tatsächlich nicht tun. Stattdessen sollte man mit Unicode im eigenen Programm explizit korrekt umgehen. Also zu Beispiel auch tatsächlich Unicode-Objekte benutzen wo sie erwartet werden.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Was mir in diesem Zusammenhang aber noch nie so ganz einleuchten wollte ist folgende Fehlermeldung:

Code: Alles auswählen

>>> 'ä'.encode('utf8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
Warum 'ascii' und 'decode'? Müsste die Fehlermeldung nicht vielmehr "Can't encode a string twice" oder so heißen...?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Hier wäre ein wenig Kontext hilfreich. Kann es sein dass es Python 2 ist? Dann kannst Du 'ä' gar nicht kodieren, weil man es dafür erst einmal dekodieren müsste. Was Python 2 an der Stelle versucht — mit ASCII als Kodierung.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@BlackJack
Ja, Python 2. Mir ist natürlich klar, dass sich ein (bei mir UTF-8) codiertes 'ä' nicht nochmals kodieren lässt. Das war ja auch, was wir beide dem TO versucht haben zu erklären.
Was mir nicht klar war ist, dass `encode()` bei strings, die nicht unicode sind versucht, diese erstmal zu dekodieren. Das erklärt natürlich den Wortlaut der Fehlermeldung.
Aber weshalb versucht `encode()` das? Ist das nicht schon ein wenig zu viel Magie? Warum nicht einfach eine Fehlermeldung im Sinne von zwei mal codieren geht nicht?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Tja, dass das zu viel Magie ist könnte man in der Tat argumentieren. Ich denke weswegen das gemacht wird, ist das man so einfacher ASCII-Zeichenketten mit Unicode mischen kann. Jedes mal wenn irgend wo `unicode` gebraucht aber `str` übergeben wird, versucht Python das als ASCII zu dekodieren. Darum können APIs wie `ElementTree` zum Beispiel Werte als `str` zurück geben wenn alle Zeichen im ASCII-Bereich sind und `unicode` falls dem nicht so ist. Um Speicherplatz zu sparen. Und man kann mit jedem beliebigen Wert der da zurück gegeben wird ``value.encode('UTF-8')`` machen, zum Beispiel um ihn in eine Datei zu schreiben, ohne zwischen `str` und `unicode` unterscheiden zu müssen.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@BlackJack
Ok, das leuchtet ein. Damit sind Dinge wie

Code: Alles auswählen

>>> u'a' + 'a'
u'aa'
>>> 'a' + u'a'
u'aa'
möglich, die eigentlich einen "TypeError: cannot concatenate 'str' and 'unicode' objects" erzeugen müssten.
Wenn das nicht möglich wäre, dürfte auch

Code: Alles auswählen

>>> 1 + 1.1
2.1
nicht erlaubt sein.

Wobei Python 3 durch das Prinzip "strings sind erstmal unicode" konsequenter geworden ist:

Code: Alles auswählen

>>> 'a'.encode('utf8') + a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't convert 'bytes' object to str implicitly
Mir persönlich ist diese Klarheit lieber...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Antworten