Seite 1 von 2
String zusammensetzen
Verfasst: Dienstag 12. März 2013, 14:23
von peddy
Hallo,
ich möchte den Text für eine Email zusammensetzen und stelle mich dabei gerade etwas doof an

Ziel soll es sein die drei Personen untereinander stehen zu haben. Also so:
Hallo,
diese neuen Mitarbeiter wurden gefunden:
- Ute Schneider
- Peter Muster
- Manuela Becker
Ich dachte ich könnte mit \n ein Newline einbauen, aber das klappt im unteren Beispiel nicht.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
liste = [(372, u'Schneider', u'Ute', u'201303'),
(470, u'Muster', u'Peter', u'201303'),
(526, u'Becker', u'Manuela', u'201303')]
def build_email_text(liste):
text = ""
for item in liste:
text += `item[2] + " " + item[1] + "\n"`
email_text = """Hallo,
diese neuen Mitarbeiter wurden gefunden:
{}""".format(text)
return email_text
if __name__ == '__main__':
print build_email_text(liste)
Re: String zusammensetzen
Verfasst: Dienstag 12. März 2013, 14:30
von xeike
Wie wäre es mit:
(also ohne Ticks)
Xe
Re: String zusammensetzen
Verfasst: Dienstag 12. März 2013, 14:36
von BlackJack
@peddy: Wie bist Du denn bitte auf die Backticks gekommen? Das ist eine veraltete Möglichkeit die `repr()`-Funktion zu verwenden, und diese Darstellung ist ja gerade explizit nicht für Endbenutzer sondern für Programmierer zur Fehlersuche gedacht.
Code: Alles auswählen
personen = [
(372, u'Schneider', u'Ute', u'201303'),
(470, u'Muster', u'Peter', u'201303'),
(526, u'Becker', u'Manuela', u'201303'),
]
def build_email_text(liste):
return (
'Hallo,\n'
'\n'
'diese neuen Mitarbeiter wurden gefunden:\n'
+ '\n'.join(
'{0} {1}'.format(vorname, name) for _, name, vorname, _ in personen
)
)
if __name__ == '__main__':
print build_email_text(personen)
Re: String zusammensetzen
Verfasst: Dienstag 12. März 2013, 14:49
von peddy
BlackJack hat geschrieben:Wie bist Du denn bitte auf die Backticks gekommen? Das ist eine veraltete Möglichkeit die `repr()`-Funktion zu verwenden, und diese Darstellung ist ja gerade explizit nicht für Endbenutzer sondern für Programmierer zur Fehlersuche gedacht.
Wenn ich das noch wüsste. Ich habe so viel probiert, dass ich mich nicht mehr genau erinnern kann.
Re: String zusammensetzen
Verfasst: Dienstag 12. März 2013, 15:55
von Sirius3
oder:
Code: Alles auswählen
personen = [
(372, u'Schneider', u'Ute', u'201303'),
(470, u'Muster', u'Peter', u'201303'),
(526, u'Becker', u'Manuela', u'201303'),
]
def build_email_text(personen):
return """Hallo,
diese neuen Mitarbeiter wurden gefunden:
{}
""".format('\n'.join(map('{0[2]} {0[1]}'.format,personen))
if __name__ == '__main__':
print build_email_text(personen)
Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 11:09
von peddy
Jetzt habe ich ein weiteres Problem festgestellt. Die Daten kommen eigentlich von Sqlite, daher werden sie als Unicode geliefert. Habe ich einen Namen mit Umlaut kommt es zur Fehlermeldung.
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 1: ordinal not in range(128)
Code: Alles auswählen
personen = [
(372, u'K\xf6ne', u'Ute', u'201303'),
(470, u'Muster', u'Peter', u'201303'),
(526, u'Becker', u'Manuela', u'201303'),
]
Entweder muss ich den Unicode in UTF-8 umwandeln oder dieser Abschnitt muss mit Unicode umgehen können:
Code: Alles auswählen
def build_email_text(liste):
return (
'Hallo,\n'
'\n'
'diese neuen Mitarbeiter wurden gefunden:\n'
+ '\n'.join(
'{0} {1}'.format(vorname, name) for _, name, vorname, _ in personen
)
)
Im Moment eine harte Nuss für mich. Leider kann man Listen und Tuples nicht Encodieren. Wo würdet ihr am ehesten ansetzen?
Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 11:42
von Sirius3
wenn der Funktionsname richtig gewählt wurde, handelt es sich ja um einen Email-Text.
Das richtige vorgehen ist also, beim Senden der email das passende Encoding (z.B. utf-8) einzustellen und den Email-Text in diesem Schritt mit .encode auch erst umzuwandeln.
Die interne Verarbeitung sollte von Anfang bis Ende auf Unicode-Strings basieren und niemals mit codierten Byte-Strings gemischt werden.
Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 13:50
von peddy
Ok, durchgehend mit Unicode arbeiten und erst am Ende umwandeln klingt vernünftig, leider macht mir die Zeile mit dem join einen Strich durch die Rechnung.
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 1: ordinal not in range(128)
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
personen = [
(372, u'K\xf6ne', u'Ute', u'201303'),
(470, u'Muster', u'Peter', u'201303'),
(526, u'Becker', u'Manuela', u'201303'),
]
print '\n'.join('{0} {1}'.format(vorname, name) for _, name, vorname, _ in personen)
Ich habe den Verdacht, dass in den Variablen vorname und name kein Unicode mehr ankommt. Ich habe auch schon mal was wie unicode(name) probiert, aber alles ohne Erfolg.
Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 13:58
von EyDu
Manchmal liegt es aber auch daran, dass nicht alle Strings im Code als Unicode abgelegt sind ...

Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 14:10
von peddy
EyDu hat geschrieben:Manchmal liegt es aber auch daran, dass nicht alle Strings im Code als Unicode abgelegt sind ...

Mhhh, die Felder für Name und Vorname sind doch alle Unicode ( u'Wert' ).
Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 14:11
von JonasR
Das sind aber nicht die einzigen strings ;D
Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 14:31
von Sr4l
Ich kann dein Problem nicht so ganz nachvollziehen, auch unter Python2 hat man doch eigentlich keine Probleme mit Zeichen außerhalb des ASCII Bereichs zuarbeiten.
Du schreibst in deine Datei ein:
am Anfang, schreibst alles so wie du es normal auch tust, also ohne manuell zu escapen und ohne unicode literals und fertig.
Wenn Daten von außerhalb kommen z.B aus einer Datenbank dann stellt man dort als encodeing noch UTF-8 ein und fertig. Oder wenn das nicht geht, ich glaube bei ConfigParser ist das so?, hantiert man bevor man mit den Daten arbeitet mit einem value.encode("utf8"), bzw. .decode("utf8") je nachdem ob man speicher oder ob man liest.
*edit* noch etwas, dein "\xf6" ist latin-1 kein utf-8 ("\xc3\xb6")
Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 14:52
von peddy
Sr4l hat geschrieben:Ich kann dein Problem nicht so ganz nachvollziehen, auch unter Python2 hat man doch eigentlich keine Probleme mit Zeichen außerhalb des ASCII Bereichs zuarbeiten.
Du schreibst in deine Datei ein:
am Anfang, schreibst alles so wie du es normal auch tust, also ohne manuell zu escapen und ohne unicode literals und fertig.
Das geht nicht in meinem Fall. Das Script ist nur von mir vereinfacht worden, damit man den Fehler leichter nachvollziehen kann. Den Unicode bekomme ich ursprünglich von einer SQL-Datenbank.
Sr4l hat geschrieben:
Wenn Daten von außerhalb kommen z.B aus einer Datenbank dann stellt man dort als encodeing noch UTF-8 ein und fertig. Oder wenn das nicht geht, ich glaube bei ConfigParser ist das so?, hantiert man bevor man mit den Daten arbeitet mit einem value.encode("utf8"), bzw. .decode("utf8") je nachdem ob man speicher oder ob man liest.
Weiter oben wurde mir empfohlen meinen Text als Unicode zusammen zu bauen und erst am Schluss ein encode zu machen. Daher habe ich mein Augenmerk erst mal auf dieses Verfahren gerichtet.
Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 15:10
von BlackJack
@peddy: Du suchst das Problem wahrscheinlich an falscher Stelle. Trenne mal das erstellen des auszugebenen Textes von der Ausgabe mit ``print``. Dann wirst Du sehr wahrscheinlich feststellen, dass die Ausgabe das Problem ist. Du kannst Unicode nicht (immer) einfach so ausgeben, denn wenn die Zeichen das Programm verlassen müssen sie an irgendeiner Stelle wieder in Bytes umgewandelt werden. Und wenn Python an der Stelle nicht raten kann mit welcher Kodierung das passieren soll, wird ASCII genommen. Wenn dann nicht alles im ASCII-Bereich ist, dann gibt es diesen Fehler.
Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 15:19
von Sr4l
peddy hat geschrieben:Das geht nicht in meinem Fall. Das Script ist nur von mir vereinfacht worden, damit man den Fehler leichter nachvollziehen kann. Den Unicode bekomme ich ursprünglich von einer SQL-Datenbank.
Das habe ich gelesen, das Verhalten von Datenbanken kann man aber ändern.
peddy hat geschrieben:Weiter oben wurde mir empfohlen meinen Text als Unicode zusammen zu bauen und erst am Schluss ein encode zu machen. Daher habe ich mein Augenmerk erst mal auf dieses Verfahren gerichtet.
Wenn du weiterhin überall mit Unicode arbeiten willst dann musst du, das mit dienen literals auch durchziehen, also auch in den Strings vom formatieren '{0} {1}'.
Oder du versuchts es mit einem, future import, da bin ich mir jedoch nicht sicher was das alles für Seiteneffekte haben kann, am Anfang.
Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 16:17
von BlackJack
@Sr4l: Das muss man nicht mit den Literalen Zeichenketten durchziehen. Nur wenn da etwas ausserhalb von ASCII enthalten ist. Dann fliegt einem an der entsprechenden Stelle aber auch eine Ausnahme um die Ohren.
Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 16:48
von Sirius3
Sr4l hat geschrieben:*edit* noch etwas, dein "\xf6" ist latin-1 kein utf-8 ("\xc3\xb6")
Die escape-Sequenz \x.. in Unicode-Strings bedeutet einfach, dass ein Unicode-Zeichen als 2-stellige Hexzahl angegeben wird
und ist äquivalent zu \u00xx.
Solange sich Strings auf 7bit beschränken lassen sich Unicode- und Byte-Strings in Python ohne weitere Umwandlung kombinieren.
Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 16:51
von Sr4l
BlackJack hat geschrieben:@Sr4l: Das muss man nicht mit den Literalen Zeichenketten durchziehen. Nur wenn da etwas ausserhalb von ASCII enthalten ist. Dann fliegt einem an der entsprechenden Stelle aber auch eine Ausnahme um die Ohren.
Kann dir jetzt nicht ganz folgen. Mit "nur wenn außerhalb von ASCII" meinst du: "kein literal", u"beim bösen aber schon" ?
Bei mir funktioniert das aber nicht mit .format().
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
for name in [u"a", u"ä", u"ö", u"ü"]:
print repr(name)
print repr(u"{0}".format(name))
print repr("{0}".format(name))
u'a'
u'a'
'a'
u'\xe4'
u'\xe4'
Traceback (most recent call last):
File "test.py", line 6, in <module>
print repr("{0}".format(name))
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 0: ordinal not in range(128)
Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 17:15
von Sr4l
Code: Alles auswählen
In [1]: u = u"ä"
In [2]: s = "s"
In [3]: s + u
Out[3]: u's\xe4'
In [4]: "%s%s"%(s, u)
Out[4]: u's\xe4'
In [5]: "{} {}".format(s, u)
---------------------------------------------------------------------------
UnicodeEncodeError Traceback (most recent call last)
<ipython-input-5-800d004aa231> in <module>()
----> 1 "{} {}".format(s, u)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 0: ordinal not in range(128)
In [6]: " ".join([s, u])
Out[6]: u's \xe4'
In [7]:
Das ist ein Bug oder?
Alle Varianten von str + unicode ergeben unicode, außer bei format?!
Re: String zusammensetzen
Verfasst: Mittwoch 13. März 2013, 17:23
von BlackJack
@Sr4l: `str.format()` scheint tatsächlich nur mit `str` beziehungsweise `unicode` im ASCII-Bereich klar zu kommen. Bin ich bis jetzt noch nicht drüber gestolpert — ich verwende wohl immer noch zu oft den ``%``-Operator.
