Seite 1 von 1
Unicode (verständnis)Problem
Verfasst: Montag 9. Juli 2012, 15:34
von lackschuh
Hallo
Bei nachstehendem Skript funktioniert die Unicode Umwandlung irgendwie nicht ganz.
Code: Alles auswählen
#!/usr/bin/env python
#-*- coding: utf-8 -*-
import smtplib as s
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header
from email.utils import formataddr
un = "xxxxxx"
pw = "xxxxxx"
print u"Bitte Name des Empfängers eingeben:"
name = raw_input().encode(' utf-8')
print u"Bitte Mailadresse eingeben:"
to = raw_input().encode(' utf-8')
to = formataddr((str(Header(u"%s" % name, ' utf-8')), "%s" % to))
print u"Bitte Name des Absenders eingeben:"
abName = raw_input().encode(' utf-8')
print u"Bitte Mailadresse eingeben:"
me = raw_input().encode(' utf-8')
me = formataddr((str(Header(u'%s' % abName, ' utf-8')), "%s" % me))
print u"Bitte Betreff eingeben:"
subject = raw_input().encode(' utf-8')
subject = str(Header(u'%s' % subject, ' utf-8'))
print u"Bitte Text eingeben:"
nachricht = raw_input().encode(' utf-8')
text = u'%s' % nachricht
msg = MIMEMultipart('alternative')
msg.set_charset('utf8')
msg['Subject'] = subject
msg['From'] = me
msg['To'] = to
part1 = MIMEText(text.encode('utf-8'), _charset='utf-8')
msg.attach(part1)
obj = s.SMTP("xxxx.xxxxx.xx:587")
obj.starttls()
obj.login(un, pw)
obj.sendmail(me, to, msg.as_string())
dir(obj)
obj.quit()
print 'Mail erfolgreich versendet'
Wenn ich einen Namen mit Ü, Ä é etc. eingebe, dann erscheint folgende Meldung:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xf6 in position 1: ordinal not in range(128)
Aber wenn ich alles (also utf-8) durch iso-8859-1 ersetze, dann kommt die Mail problemlos an und alle Umlaute werden auch korrekt angezeigt.
Was muss ich tun, wenn ich
verwenden will und nicht
bzw. wo hab ich was verwechselt oder nicht kapiert?
mfg
Re: Unicode (verständnis)Problem
Verfasst: Montag 9. Juli 2012, 16:14
von BlackJack
@lackschuh: Der Kodierungskommentar gilt einzig und alleine für den *Quelltext* des Moduls und sollte der Kodierung entsprechen, in der der Quelltext auch tatsächlich gespeichert wurde.
`raw_input()` gibt eine Zeichenkette (`str`) zurück und da macht es keinen Sinn `encode()` mit einer Zeichenkodierung aufzurufen. Die ist ja bereits irgendwie kodiert. Und wenn man das trotzdem macht, versucht Python das `str`-Objekt erst als ASCII in ein `unicode`-Objekt zu dekodieren um *das* dann mit der angegebenen Kodierung wieder zu einem `str` zu kodieren. Das ist sinnfrei und führt bei Zeichen ausserhalb von ASCII genau zu der gezeigten Ausnahme.
Die diversen ``'%s' % obj`` und ``u'%s' % obj`` sind auch komisch bis unsinnig. Wenn man das *wirklich* machen will, dann wären `str()`- und `unicode()`-Aufrufe zumindest schon einmal verständlicher beim Lesen.
Re: Unicode (verständnis)Problem
Verfasst: Dienstag 10. Juli 2012, 08:13
von mutetella
Ich versuche mich mal an einer Antwort...
'raw_input()' liefert Dir einen string, der mit Deinem Systemencoding kodiert ist. Das heißt, wenn Dein System mit utf8 kodiert, dann bekommst Du
Code: Alles auswählen
>>> raw_input()
ä
'\xc3\xa4' #Das ist ein utf-8 kodierter string
Läuft Dein System unter iso8859 (latin), dann schaut es so aus:
Code: Alles auswählen
>>> raw_input()
ä
'\xe4' #Das ist ein iso-8859-1 kodierter string
Deinem Beitrag entnehme ich, dass Dein System utf8 verwendet. Wie BlackJack ja bereits geschrieben hat ist der string, den Dir 'raw_input()' liefert bereits codiert, in Deinem Fall als utf8. Deshalb bekommst Du einen Fehler geworfen, da Du einen utf8-kodierten string nochmal in einen utf8-string kodieren möchtest.
Es empfiehlt sich, programmintern mit unkodierten strings, sprich unicode-strings zu arbeiten. Einen solchen string erhälts Du z. B. so:
Code: Alles auswählen
>>> import sys
>>> ENCODING = sys.getfilesystemencoding()
>>> raw_input().decode(ENCODING)
ä
u'\xe4'
Diesen unicode-string kannst Du dann wieder in ein encoding wie utf8 oder iso8859 kodieren. Also:
1. 'raw_input()' liefert Dir einen bereits kodierten string.
2. Die Kodierung, die Du in Deinem Modul über '#-*- coding: irgendwas -*-' angibst hat damit nichts zu tun
3. Es empfiehlt sich, programmintern mit unicode-strings zu arbeiten
4. unicode ist KEIN encoding!
mutetella
Re: Unicode (verständnis)Problem
Verfasst: Dienstag 10. Juli 2012, 08:24
von lackschuh
BlackJack hat geschrieben:`raw_input()` gibt eine Zeichenkette (`str`) zurück und da macht es keinen Sinn `encode()` mit einer Zeichenkodierung aufzurufen.
Danke für die Infos. Ich hab mal die ganzen `encode()` weggemacht und es geht auch nun ohne. Das erste Problem lag an Eclipse. Hab Eclipse nun so eingestellt, dass die Konsole die Umlaute auch ohne .encode() korrekt anzeigt.
BlackJack hat geschrieben:Die diversen ``'%s' % obj`` und ``u'%s' % obj`` sind auch komisch bis unsinnig. Wenn man das *wirklich* machen will, dann wären `str()`- und `unicode()`-Aufrufe zumindest schon einmal verständlicher beim Lesen.
Was wäre eine bessere Lösung, wenn ich noch am Anfang die Daten per Konsole eingeben will?
mfg
Re: Unicode (verständnis)Problem
Verfasst: Dienstag 10. Juli 2012, 09:52
von mutetella
lackschuh hat geschrieben:Das erste Problem lag an Eclipse. Hab Eclipse nun so eingestellt, dass die Konsole die Umlaute auch ohne .encode() korrekt anzeigt.
Zu Eclipse kann ich nichts sagen... ich hatte aber mit IPython bis zur Version 0.11 (seit 0.12 klappt's) auch Momente, in denen ich kurz vor dem Wahnsinn stand, weil einfach nicht korrekt kodiert wurde...
Ich kann Dir nur empfehlen, gerade beim Testen der richtigen Anzeige auf die pythoneigene Konsole zurückzugreifen.
lackschuh hat geschrieben:Ich hab mal die ganzen `encode()` weggemacht und es geht auch nun ohne.
Wobei das nichts mit Eclipse zu tun hat. Die Erklärung dafür hast Du ja schon bekommen.
lackschuh hat geschrieben:BlackJack hat geschrieben:Die diversen ``'%s' % obj`` und ``u'%s' % obj`` sind auch komisch bis unsinnig. Wenn man das *wirklich* machen will, dann wären `str()`- und `unicode()`-Aufrufe zumindest schon einmal verständlicher beim Lesen.
Was wäre eine bessere Lösung, wenn ich noch am Anfang die Daten per Konsole eingeben will?
BlackJack hat es ja schon angedeutet:
Warum möchtest Du das denn überhaupt machen?
Was möchtest Du damit erreichen?
Nochmal:
- 'raw_input()' liefert je nach Systemencoding einen kodierten string (meistens utf8 oder ein iso8859 Encoding)
- Wenn Du einen unicode-string brauchst, erhältst Du den über 'unicode()' oder die 'decode()'-Methode des jeweiligen strings
mutetella
Re: Unicode (verständnis)Problem
Verfasst: Dienstag 10. Juli 2012, 13:09
von Leonidas
@mutetella: ``sys.getfilesystemencoding()`` sagt dir nicht das Encoding von Stdin, daher kann das klappen, muss aber nicht. Da ist es schon sinnvoller zu gucken was das Locale ist, aber selbst das ist nicht unbedingt Zielführend.
Re: Unicode (verständnis)Problem
Verfasst: Dienstag 10. Juli 2012, 14:22
von mutetella
@Leonidas: Ok, dann also 'locale.getpreferredencoding()', oder?
Ich dachte halt, nachdem 'stdin' ja auch 'irgendwie' 'ne Datei ist kann mit größerer Wahrscheinlichkeit davon ausgegangen werden, dass strings von 'stdin' auch im filesystemencoding vorliegen.
mutetella
Re: Unicode (verständnis)Problem
Verfasst: Dienstag 10. Juli 2012, 14:59
von cofi
Und wenn man Glueck hat, hilft das
Code: Alles auswählen
In [1]: import sys
In [2]: sys.stdin.encoding
Out[2]: 'UTF-8
Std* sind zwar Dateien, aber befinden sich nicht im Dateisystem, zumindest nicht in einem "normalen".

Re: Unicode (verständnis)Problem
Verfasst: Dienstag 10. Juli 2012, 15:14
von deets
mutetella hat geschrieben:@Leonidas: Ok, dann also 'locale.getpreferredencoding()', oder?
Ich dachte halt, nachdem 'stdin' ja auch 'irgendwie' 'ne Datei ist kann mit größerer Wahrscheinlichkeit davon ausgegangen werden, dass strings von 'stdin' auch im filesystemencoding vorliegen.
Das hat doch nichts miteinander zu tun. Das eine gilt fuer die *Namen* einer Datei, das andere fuer deren Inhalt - und ist zB von Terminal-Settings abhaengig, die sich jederzeit aendern koennen. Das der Filenamen nicht so.
Diez
Re: Unicode (verständnis)Problem
Verfasst: Dienstag 10. Juli 2012, 15:47
von mutetella
@deets
Hab's auch gerade
gelesen...
mutetella
Re: Unicode (verständnis)Problem
Verfasst: Mittwoch 11. Juli 2012, 01:29
von Leonidas
mutetella hat geschrieben:Ich dachte halt, nachdem 'stdin' ja auch 'irgendwie' 'ne Datei ist kann mit größerer Wahrscheinlichkeit davon ausgegangen werden, dass strings von 'stdin' auch im filesystemencoding vorliegen.
Das mit dem Filesystem-Encoding ist eh eine großer Quatsch. In NTFS sind ist das Encoding der Dateien UTF-16, in FAT kanns alles mögliche sein und in Unix kanns alles mögliche sein bunt gemischt, weil in Unix-Dateisystemen die Dateinamen binär sind, jedem User und App steht frei seine Dateinamen in UTF-8 bis -32, Big5, EUC-JP, KOI-8R oder was auch immer zu kodieren. Und in Mac OS X ändern sie die Art wie sie Normalisieren von Release zu Release. Das ganze war ja auch in Python 3 so ein Problem mit dem Öffnen von Dateien.